INFO: Dieses Forum nutzt Cookies...
Cookies sind für den Betrieb des Forums unverzichtbar. Mit der Nutzung des Forums erklärst Du dich damit einverstanden, dass wir Cookies verwenden.

Es wird in jedem Fall ein Cookie gesetzt um diesen Hinweis nicht mehr zu erhalten. Desweiteren setzen wir Google Adsense und Google Analytics ein.


Antwort schreiben 

Einbindung DLL mit geschachtelten Structures



Wenn dein Problem oder deine Frage geklärt worden ist, markiere den Beitrag als "Lösung",
indem du auf den "Lösung" Button rechts unter dem entsprechenden Beitrag klickst. Vielen Dank!

07.05.2017, 15:48
Beitrag #1

lab-falballa Offline
LVF-Neueinsteiger


Beiträge: 6
Registriert seit: Apr 2016

15
2011
DE


Deutschland
Einbindung DLL mit geschachtelten Structures
Hallo zusammen,

ich versuche den Delay-Generator SG08P2 von BME Bergmann in Labview anzusteuern. Ich habe dafür eine DLL-Funktion ReadParameters, mit der ich eine Datei *.g0y einlesen können sollte. Leider gibt mir mein Programm aktuell den Fehler 1097 aus und es werden hier structs verwendet, die selbst auch wieder structs und unions enthalten. Hier der Ausschnitt aus der Hilfedatei:

long ReadParameters(DG_BME_State* p_DGS, int* p_module, BOOL* p_CalibrateTiming, unsigned long* p_CalibrationLevel, char* FileName);

typedef struct
{
DG_BME_Control Control;
int BaseAddress;
int DG_Product;
BOOL Master;
int BusNumber;
char ip_address[40];
} DG_BME_State;

mit
typedef struct
{
DelayChannelData T0,A,B,C,D,E,F;
DelayTriggerData DT;
BOOL Gate_AB;
unsigned long GateFunction;
unsigned long OutputLevel;
unsigned long DG_Product;
unsigned long PulseWidth;
} DG_BME_Control;

mit
typedef struct
{
union
{
double FireFirst;
double DelayTime[MemDepth];
};
double PulseWidth[MemDepth];
double SetBack;
unsigned long StepBack[MemDepth];
signed long ListLength;
signed long OutputModulo;
signed long OutputOffset;
unsigned long GoSignal;
unsigned long DoneSignal;
BOOL Positive;
BOOL Terminate;
BOOL HighDrive;
BOOL Disconnect;
BOOL OntoMsBus;
BOOL InputPositive;
} DelayChannelData;
und
typedef struct
{
double TriggerLevel;
double GateLevel;
union
{
double InternalClock;
double InhibitTrigger;
};
double InhibitSecondary;
double ForceTrigger;
double StepBackTime;
double GateDelay;
unsigned long BurstCounter;
unsigned long DelaySecondary;
union
{
_int64 PresetLong;
unsigned long PresetValue;
};
union
{
unsigned long DivideBy;
struct
{
unsigned short OscillatorDivider;
unsigned short TriggerDivider;
};
};
unsigned long TriggerMultiplier;
unsigned long ClockSource;
unsigned long GateDivider;
unsigned long MS_Bus;
BOOL PositiveGate;
BOOL IgnoreGate;
BOOL SynchronizeGate;
BOOL ClockEnable;
BOOL InternalTrigger;
BOOL InternalArm;
BOOL SoftwareTrigger;
BOOL RisingEdge;
BOOL StopOnPreset;
BOOL ResetWhenDone;
BOOL TriggerEnable;
BOOL Terminate;
BOOL GateTerminate;
BOOL UseF;
} DelayTriggerData;

In Labview ist das bei mir dann:
int32_t ReadParameters(void *p_DGS, int32_t *p_module, uint16_t p_CalibrateTiming, uint32_t *p_CalibrationLevel, CStr FileName);
(s. angehängte Datei, Typdefinition, dlls und die zip-Datei (die zip ist die g0y-Datei, die reingeladen werden soll - die Werte sind anders als "0" bzw. "False", so dass man deutlich sehen müsste, wenn das Laden klappt).

Falls irgendjemand Ideen hat, woran es liegen könnte, dass der Aufruf nicht klappt, ich bin für jeden Hinweis dankbar.

VG

p.s. Hintergrund, falls es interessiert: Ich benutze als external Clock die Frequenz meines Femtosekunden-Oszillators mit 79.39 MHz und dann als Gate das Triggersignal meines Chirped Amplifier Verstärkers mit 10 kHz. Bei dieser Kombi funktioniert mit dem mitgelieferten Programm zur Ansteuerung der Delay-Generator-Karte alles soweit gut: Ich bekomme ein Trigger-Signal, was sich bei Verstellen des Delays kontinuierlich verschiebt und einen geringen Jitter von etwa 200 ps zeigt. (Leider habe ich einen Pockelszellentreiber, der ein Fenster von kleiner 5 ns (bei 10% der Amplitude) hat, so dass ich mir mehr zeitlichen Jitter nicht leisten kann.) Wenn ich das Ganze nun mit einem Programm aus mitgelieferten Sub-VIs mache, funktioniert es leider nicht (leider gibt es für Labview keinen Support vom Delay-Karten-Hersteller) - irgendeine Einstellung scheint noch falsch zu sein und sowohl der Delay lässt sich nicht kontinuierlich verstellen als auch der Jitter springt bei höheren Delays auf ungefährt 1 ns. Deshalb möchte ich die Parameterdatei *.g0y, die durch das mitgelieferte Programm erstellt wurde, in Labview öffnen, in der Hoffnung den Fehler zu umgehen.


Angehängte Datei(en)
15.0 .vi  Read Parameters.vi (Größe: 32,4 KB / Downloads: 348)

15.0 .ctl  Parameters.ctl (Größe: 16,45 KB / Downloads: 334)

10.0 .dll  DelayGenerator.dll (Größe: 163,5 KB / Downloads: 347)

4.0 .dll  PlxApi641.dll (Größe: 121,5 KB / Downloads: 347)

0.0 .zip  170505_Parameter-DG.zip (Größe: 1,43 KB / Downloads: 344)
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren to top
Anzeige
09.05.2017, 23:34
Beitrag #2

rolfk Offline
LVF-Guru
*****


Beiträge: 2.305
Registriert seit: Jun 2007

alle seit 6.0
1992
EN

2901GG
Niederlande
RE: Einbindung DLL mit geschachtelten Structures
(07.05.2017 15:48 )lab-falballa schrieb:  Hallo zusammen,

ich versuche den Delay-Generator SG08P2 von BME Bergmann in Labview anzusteuern. Ich habe dafür eine DLL-Funktion ReadParameters, mit der ich eine Datei *.g0y einlesen können sollte. Leider gibt mir mein Programm aktuell den Fehler 1097 aus und es werden hier structs verwendet, die selbst auch wieder structs und unions enthalten. Hier der Ausschnitt aus der Hilfedatei:

long ReadParameters(DG_BME_State* p_DGS, int* p_module, BOOL* p_CalibrateTiming, unsigned long* p_CalibrationLevel, char* FileName);

typedef struct
{
DG_BME_Control Control;
int BaseAddress;
int DG_Product;
BOOL Master;
int BusNumber;
char ip_address[40];
} DG_BME_State;

mit
typedef struct
{
DelayChannelData T0,A,B,C,D,E,F;
DelayTriggerData DT;
BOOL Gate_AB;
unsigned long GateFunction;
unsigned long OutputLevel;
unsigned long DG_Product;
unsigned long PulseWidth;
} DG_BME_Control;

mit
typedef struct
{
union
{
double FireFirst;
double DelayTime[MemDepth];
};
double PulseWidth[MemDepth];
double SetBack;
unsigned long StepBack[MemDepth];
signed long ListLength;
signed long OutputModulo;
signed long OutputOffset;
unsigned long GoSignal;
unsigned long DoneSignal;
BOOL Positive;
BOOL Terminate;
BOOL HighDrive;
BOOL Disconnect;
BOOL OntoMsBus;
BOOL InputPositive;
} DelayChannelData;
und
typedef struct
{
double TriggerLevel;
double GateLevel;
union
{
double InternalClock;
double InhibitTrigger;
};
double InhibitSecondary;
double ForceTrigger;
double StepBackTime;
double GateDelay;
unsigned long BurstCounter;
unsigned long DelaySecondary;
union
{
_int64 PresetLong;
unsigned long PresetValue;
};
union
{
unsigned long DivideBy;
struct
{
unsigned short OscillatorDivider;
unsigned short TriggerDivider;
};
};
unsigned long TriggerMultiplier;
unsigned long ClockSource;
unsigned long GateDivider;
unsigned long MS_Bus;
BOOL PositiveGate;
BOOL IgnoreGate;
BOOL SynchronizeGate;
BOOL ClockEnable;
BOOL InternalTrigger;
BOOL InternalArm;
BOOL SoftwareTrigger;
BOOL RisingEdge;
BOOL StopOnPreset;
BOOL ResetWhenDone;
BOOL TriggerEnable;
BOOL Terminate;
BOOL GateTerminate;
BOOL UseF;
} DelayTriggerData;

In Labview ist das bei mir dann:
int32_t ReadParameters(void *p_DGS, int32_t *p_module, uint16_t p_CalibrateTiming, uint32_t *p_CalibrationLevel, CStr FileName);
(s. angehängte Datei, Typdefinition, dlls und die zip-Datei (die zip ist die g0y-Datei, die reingeladen werden soll - die Werte sind anders als "0" bzw. "False", so dass man deutlich sehen müsste, wenn das Laden klappt).

Falls irgendjemand Ideen hat, woran es liegen könnte, dass der Aufruf nicht klappt, ich bin für jeden Hinweis dankbar.

VG

p.s. Hintergrund, falls es interessiert: Ich benutze als external Clock die Frequenz meines Femtosekunden-Oszillators mit 79.39 MHz und dann als Gate das Triggersignal meines Chirped Amplifier Verstärkers mit 10 kHz. Bei dieser Kombi funktioniert mit dem mitgelieferten Programm zur Ansteuerung der Delay-Generator-Karte alles soweit gut: Ich bekomme ein Trigger-Signal, was sich bei Verstellen des Delays kontinuierlich verschiebt und einen geringen Jitter von etwa 200 ps zeigt. (Leider habe ich einen Pockelszellentreiber, der ein Fenster von kleiner 5 ns (bei 10% der Amplitude) hat, so dass ich mir mehr zeitlichen Jitter nicht leisten kann.) Wenn ich das Ganze nun mit einem Programm aus mitgelieferten Sub-VIs mache, funktioniert es leider nicht (leider gibt es für Labview keinen Support vom Delay-Karten-Hersteller) - irgendeine Einstellung scheint noch falsch zu sein und sowohl der Delay lässt sich nicht kontinuierlich verstellen als auch der Jitter springt bei höheren Delays auf ungefährt 1 ns. Deshalb möchte ich die Parameterdatei *.g0y, die durch das mitgelieferte Programm erstellt wurde, in Labview öffnen, in der Hoffnung den Fehler zu umgehen.

Das ist klarer Horror um so in LabVIEW zu interfacen. Aber beginne mal damit dass ein BOOL ein Windows spezifischer Datentyp ist der eine 32 Bit Integer Zahl darstellt, wo 0 FALSE bedeutet und alles andere TRUE. LabVIEW Booleans sind aber
nur 8 Bit gross. Daneben müsstest Du natürlich auch noch auf das Alignment jedes einzelenen Elementes achten. Das heisst dass jedes Element in der struct auf eine Addresse "alignt" wird die ein Vielfaches vom kleineren der Zwei Werte "eigene Bytegrösse der Variable" und dem "Default Alignment"ist. Unter LabVIEW 32 Bit für Windows packt LabVIEW aber alle Elemente in einem Cluster kompakt hintereinander in den Speicher. Die meisten DLLs werden aber mit einem Default Alignment von 8 Byte compiliert. Das heisst das für ein BOOL (32 bit integer) dieses Element in der struct normalerweise auf eine durch 4 teilbare Addresse gelegt wird. Wenn davor zum Beispiel nur ein 8 bit Integer liegt, werden in der struct 3 extra filler bytes anwesend sein vor dem BOOL. LabVIEW 64 Bit für Windows benützt dagegen dieselben 8 Byte aligment die auch bei DLLs üblicherweise verwendet werden. Aber man sollte dabei nicht vergessen, dass der DLL Programmierer dieses Default alignment selbstverständlich ändern kann. Wenn man Glück hat macht er das mit #pragma pack() statements in der Header Datei so dass man es sehen kann, oder er ändert es in den Projekteinstellungen und dokumentiert das hoffentlich in der Dokumentation zur DLL.

Durch die Verwendung von LabVIEW Booleans anstelle von 32 bit Integers (und eventuelles nicht Beachten von Alignments) wird die ganze Struktur die LabVIEW an die DLL übergibt wesentlich kürzer, so dass die DLL beim Beschreiben dieser struct unweigerlich über das Ende des in LabVIEW allozierten Speicherbereichs schreibt und dabei zumindest Daten zerstört die sie nicht sollte oder eventuel eine Speicherverletzung auslöst was den Fehler 1097 verursachen kann.

Der absolute Hammer allerdings ist, dass die Konfiguration einiger Deiner Parameter vollkommen falsch ist.
p_module stimmt noch, das ist eine Referenz auf einen int, also einen Pointer auf einen 32 Bit Wert, aber p_ClaibrateTiming ist schwer falsch. BOOL ist wie gesagt ein 32 Bit integer und wie durch das Sternchen angegeben ebenfalls eine Referenz, aber Du machst daraus einen uInt16 und übergibst ihn fröhlich als Wert statt als Pointer auf den Wert. p_CalibrationLevel stimmt dann wieder. Der Pfad scheint auch zu stimmen.

Eine undeutlichkeit ist ob der erste Parameter wirklich nur ein Pointer auf eine struct ist oder aber wirklich ein Array dieser structs sein sollte. Da die Funktion keine Möglichkeit vorsieht um ihr mitzuteilen wie viele Arrayelement dieser Parameter hat, scheint es dass es nur ein einzelner struct ist, ABER!!!!!!! die Beschreibung sagt zugleich ausdrücklich:

Zitat:Reserve enough memory for this structure to take all data for the delay generators that will be read from file.

Und die Funktion liefert als Returnwert für wieviele Delaygeneratoren Informationen züruckgegeben wurden!!!!

Eventuel gilt dies auch für den 2ten Parameter. Auch hier ist die Beschreibung so richtig schön undeutlich.

Alles in allem wie schon gesagt, ein Alptraum zum benützen, selbst von C Code aus.

Rolf Kalbermatter
Technische Universität Delft, Dienst Elektronik und Mechanik
https://blog.kalbermatter.nl
Webseite des Benutzers besuchen Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren to top
10.05.2017, 08:28
Beitrag #3

lab-falballa Offline
LVF-Neueinsteiger


Beiträge: 6
Registriert seit: Apr 2016

15
2011
DE


Deutschland
RE: Einbindung DLL mit geschachtelten Structures
Ja, ich stimme dir völlig zu: Das Ganze ist Horror.

Mit den LVBoolean hast du natürlich recht. Ich hatte da auch nochmal eine Version mit I8 gemacht, nachdem ich gepostet hatte, allerdings lief die natürlich auch nicht besser.
Beim p_CalibrateTiming ist mir ein Fehler unterlaufen - bin mir sicher, dass ich das aus einem schon gewrappten Sub-VI genommen hatte, aber ich finde es jetzt auch nicht mehr.

Auf jeden Fall vielen Dank für die Hinweise! Ich werde mich dann nochmal mit dem alignment und der Frage, wie die Einbindung der struct zu verstehen ist, beschäftigen.
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren to top
Antwort schreiben 


Möglicherweise verwandte Themen...
Themen Verfasser Antworten Views Letzter Beitrag
  Einbindung DLL funktioniert nicht Schrankwand 1 4.097 10.03.2023 18:50
Letzter Beitrag: GerdW
  ext. DLL - Einbindung Read Funktion TobSTAR 7 12.978 12.02.2017 18:40
Letzter Beitrag: rolfk
  DLL-Einbindung schlägt fehl lupus022 7 10.215 23.05.2013 11:16
Letzter Beitrag: lupus022
  Problem bei Struct Einbindung wie in C/C++ raverel 5 8.759 24.04.2013 14:22
Letzter Beitrag: raverel
  DLL-Einbindung, Struct mit verschiedenen Datentypen als Pointer übergeben hawk72 4 11.059 11.05.2012 14:41
Letzter Beitrag: hawk72
  Einbindung der Vector XL Driver Library 5.3 in LabVIEW ... nmoerchen 15 26.624 17.10.2011 07:32
Letzter Beitrag: Mik

Gehe zu: