ich muss eine DLL erstellen für die Software ProfiLab. Die will ein paar Sachen haben die ich nicht so ganz hin bekomme.
Hier die Beschreibung aus der Hilfe:
- Delphi: Procedure Calculate(PInput,POutput,PUser: PDLLParams);
C++: void _stdcall CCalculate(double *PInput, double *POutput, double *PUser)
Die ist die zentrale Berechnungsroutine Ihres DLL-Bauteils, die die Funktion des Bauteils
definiert. Mit den Parametern PINPUT, POUTPUT und PUSER bekommt die Routine drei
Zeigervariablen (Pointer) übergeben die folgende Funktion haben:
l
Der Pointer PINPUT zeigt auf einen Speicherbereich, der dazu dient die Eingangswerte des
mk:@MSITStore:C:\Programme\ProfiLab-Expert40\ProfiLab40.CHM::/Dllimport.html 20.08.2010
DLL-Import
l
l
Seite 2 von 4
Bauteils an die DLL zu übergeben.
Der Pointer POUTPUT zeigt auf einen Speicherbereich, der dazu dient die berechneten
Ausgangswerte der DLL an das Bauteil zurückzugeben.
Der Pointer PUSER stellt einen Pointer auf einen Speicherbereich zur Verfügung, in dem
die DLL eigene (lokale) Werte speichern kann. Hintergrund: Variablen, die die DLL selbst
deklariert sind globale Variablen. Werte die in diesen Variablen gespeichrt werden,
würden sich gegenseitig überschreiben, wenn man dieselbe DLL mehr als einmal in einem
ProfiLab-Projekt verwendet. Um lokale Werte speichern zu können, stellt ProfiLab der DLL
den lokalen Speicherbereich zur Verfügung, auf den PUSER zeigt. (Alternativ kann man
auch Variablen in der DLL selbst deklarieren. Dann muß man die DLL aber mehrfach unter
verschiedenen Dateinamen speichern und importieren, um sie mehrfach in einem
ProfiLab-Projekt verwenden zu können.)
Alle drei Pointer PINPUT, POUTPUT und PUSER zeigen jeweils auf einen Speicherbereich in dem
100 Variablen vom Typ EXTENDED in einem Array abgelegt sind. Die Pointer sind vom Typ
PDLLParams, dessen Deklaration in Delphi so aussieht:
type TDLLParams = array[0..100] of extended;
PDLLParams = ^TDLLParams;
In C++ wird dieser Speicherbereich z.B. als (double *PInput) übergeben.
Die Extended-Variablen des Pointers PINPUT enthalten die Eingangszustände des Bauteils. Auf
den Wert eines Eingangs des Bauteils können Sie wie folgt zugreifen:
PInput^[0] enthält den numerischen Eingangswert des 1. Eingangs,
PInput^[1] enthält den numerischen Eingangswert des 2. Eingangs, usw.
Die Extended-Variablen des Pointers POUTPUT nehmen die Ausgangszustände des Bauteils auf.
Um den Wert der Ausgänge des Bauteils zu setzen, benutzen Sie:
POutput^[0] nimmt den numerischen Ausgangswert des 1. Ausgangs auf,
POutput^[1] nimmt den numerischen Ausgangswert des 2. Ausgangs, usw.
Entsprechend können Sie mit PUser^[0] bis PUser^[99] frei verwenden um eigene Werte zu
speichern. Die Werte in diesen Variablen werden von ProfiLab mit in der Projektdatei
abgespeichert, und sind so beim nächsten Laden des Projekts wieder verfügbar. Die Variable
PUser^[100] wird von ProfiLab gesetzt, und enthält die Nummer des DLL-Bauteils in Ihrem
Projekt: 1 für DLL1, 2 für DLL2, usw.
Die Routine Calculate wird im RUN-Modus ständig von ProfiLab aufgerufen, um neue
Eingangswerte zu übergeben und neue Ausgangswerte für das Bauteil abzurufen. Diese Routine
muss daher unbedingt zeitoptimiert programmiert werden, und sollte auf keinen Fall Pausen (in
Form von SLEEP-Befehlen oder Warteschleifen) enthalten. Nach dem Abfragen der
Eingangswerte und dem Setzen der Ausgangswerte sollte die Routine so schnell wie möglich
wieder verlassen werden. Die Rechenzeit für die Routine wirkt sich unmittelbar auf die
Simulationsfrequenz von ProfiLab aus.
- Beispiel DLL-Quelltext (C++)
Die compilierte DLL finden Sie im Order BEISPIELE (C_COUNTER.DLL).
// Defines a simple 8 bit binary counter component for ProfiLab
#include <windows.h>
//---------------------------------------------------------------------------
#pragma argsused
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
return 1;
}
//---------------------------------------------------------------------------
#include <string.h>
#include <stdio.h>
#include <stddef.h>
//Index for input variables
const CLK = 0;
const RST = 1;
//Index for user variables
const CLK_OLD = 0;
const RST_OLD = 1;
const COUNT = 2;
unsigned char inputs = 2; //two inputs
unsigned char outputs = 8; //eight outputs
//Exported functions...
extern "C" __declspec(dllexport)
extern "C" __declspec(dllexport)
extern "C" __declspec(dllexport)
Channel, unsigned char *Name);
extern "C" __declspec(dllexport)
Channel, unsigned char *Name);
extern "C" __declspec(dllexport)
*POutput, double *PUser);
extern "C" __declspec(dllexport)
*POutput, double *PUser);
extern "C" __declspec(dllexport)
*POutput, double *PUser);
extern "C" __declspec(dllexport)
unsigned char _stdcall NumOutputs();
unsigned char _stdcall NumInputs();
void _stdcall GetInputName(unsigned char
void _stdcall GetOutputName(unsigned char
void _stdcall CCalculate(double *PInput, double
void _stdcall CSimStart(double *PInput, double
void _stdcall CSimStop(double *PInput, double
void _stdcall CConfigure(double *PUser);
//return number of input channels...
unsigned char _stdcall NumInputs()
{
return inputs;
}
//return number of output channels...
unsigned char _stdcall NumOutputs()
{
return outputs;
}
//return name for each input...
void _stdcall GetInputName(unsigned char Channel, unsigned char *Name)
{
if (Channel == 0)
strcpy(Name, "CLK"); //Name input 0
else
mk:@MSITStore:C:\Programme\ProfiLab-Expert40\ProfiLab40.CHM::/BeispielDllq...
20.08.2010
Beispiel DLL-Quelltext (C++)
Seite 2 von 3
strcpy(Name, "RST"); //Name input 1
}
//return name for each output...
void _stdcall GetOutputName(unsigned char Channel, unsigned char *Name)
{
sprintf(Name, "Q%i", Channel); // Name outputs Q0..Q7
}
//reset counter on start...
void _stdcall CSimStart(double *PInput, double *POutput, double *PUser)
{
int i;
PUser[COUNT] = 0;
for (i = 0; i < outputs; i++)
POutput = 0;
//RESET counter
//All outputs low
}
//check inputs and set outputs while running...
void _stdcall CCalculate(double *PInput, double *POutput, double *PUser)
{
int i, iCount;
if (PInput[RST] < 2.5)
// RST input LOW?
{
if (PUser[RST_OLD] > 2.5) //Falling edge of RST?
{
PUser[COUNT] = 0; //RESET counter
for (i = 0; i < outputs; i++) //all outputs low
POutput = 0;
}
}
PUser[RST_OLD] = PInput[RST]; //remember RST for next call
if (PInput[CLK] > 2.5) //clock input high?
{
if (PUser[CLK_OLD] < 2.5) //rising edge of CLK?
{
PUser[COUNT] += 1; //increase counter
if (PUser[COUNT] > 255)
PUser[COUNT] = 0; //check
overflow, byte limit!
iCount = PUser[COUNT]; //convert double to integer
(byte)
//Set corresponding outputs with bits set in byte
iCOUNT...
if ((iCount & 1)) POutput[0] = 5; else POutput[0] = 0;
if ((iCount & 2)) POutput[1] = 5; else POutput[1] = 0;
if ((iCount & 4)) POutput[2] = 5; else POutput[2] = 0;
if ((iCount &) POutput[3] = 5; else POutput[3] = 0;
if ((iCount & 16)) POutput[4] = 5; else POutput[4] = 0;
if ((iCount & 32)) POutput[5] = 5; else POutput[5] = 0;
if ((iCount & 64)) POutput[6] = 5; else POutput[6] = 0;
if ((iCount & 128)) POutput[7] = 5; else POutput[7] = 0;
}
}
PUser[CLK_OLD] = PInput[CLK]; // remember CLK for next call
}
// called when project is stopped...
void _stdcall CSimStop(double *PInput, double *POutput, double *PUser)
{
//nothing to do...
}
//called when button CONFIGURE is pressed in dialogue...
void _stdcall CConfigure(double *PUser)
{
MessageBox(0,"Nothing to configure", "Configure", 0);
}
//DONE!!!
Danke an jeden der hilft
