Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Typdeklarationen in C und Delphi (https://www.delphipraxis.net/131350-typdeklarationen-c-und-delphi.html)

messie 23. Mär 2009 18:36


Typdeklarationen in C und Delphi
 
Moin,

ich versuche seit einigen Tagen, ein Messgerät von National Instruments unter Delphi zum Laufen zu bringen. Ich habe eine Headerdatei und eine c-lib, die per OLE auf die tatsächliche dll zugreift. Technisch gesehen ziemlicher Unsinn weil zu langsam.

Meine aktuelle Frage: ich würde gerne aus dieser Deklaration (stellvertretend für einige hundert) einen Delphi-Aufruf machen:

Code:
int32 __CFUNC    DAQmxCreateTask         (const char taskName[], TaskHandle *taskHandle);
Das sieht dann bei mir im Prinzip so aus:
Delphi-Quellcode:
function DAQmxCreateTask(const taskName : string; var taskHandle : TTASKHANDLE) : int32; external 'NICAIU.DLL';
Das mit dem string wird natürlich nicht klappen. Array of pChar braucht eine feste Länge. PChar(string) geht in der Deklaration nicht.
Gibt es eine Möglichkeit, einen nullterminierten string als Typ zu deklarieren?

Die Basis der Übersetzungen kommt aus Dr. Bob's Tool, was doch ziemlich gestolpert ist. National Instruments gibt eine pas-Datei heraus, die vergleichbar ist und auch voller Fehler steckt (sieht auch automatisch übersetzt aus - Delphi wird von NI nicht unterstützt). Die wollen ja auch ihre überteuerten Labview-Lizenzen verkaufen.
Dabei haben sie leider die Performance vergessen. Das Problem wird sicher noch mehr Fragen aufwerfen...

Danke, Messie

Corpsman 23. Mär 2009 18:50

Re: Kann eine Typdeklaration eine Anweisung erhalten?
 
Probier mal :

Delphi-Quellcode:

Type Blub = Array of PChar;

function DAQmxCreateTask(const taskName : Blub ; var taskHandle : TTASKHANDLE) : int32; external 'NICAIU.DLL';
und

Code:
*taskHandle
müste
Delphi-Quellcode:
type PtaskHandle = ^TTASKHANDLE
sein. damit also
Delphi-Quellcode:
function DAQmxCreateTask(const taskName : Blub ; var taskHandle : PtaskHandle ) : int32; external 'NICAIU.DLL';
Evtl reicht auch
Delphi-Quellcode:
function DAQmxCreateTask(const taskName : Pchar; var taskHandle : PtaskHandle ) : int32; external 'NICAIU.DLL';
und dann itterierst du durch Taskname durch bis du auf #0 stöst

mr_emre_d 23. Mär 2009 19:12

Re: Kann eine Typdeklaration eine Anweisung erhalten?
 
Wenn man es mit "var" macht, übergibt Delphi doch automatisch (intern) einen Pointer, oder täusche ich mich da ?

messie 23. Mär 2009 19:22

Re: Kann eine Typdeklaration eine Anweisung erhalten?
 
Zitat:

Zitat von Corpsman
Evtl reicht auch
Delphi-Quellcode:
function DAQmxCreateTask(const taskName : Pchar; var taskHandle : PtaskHandle ) : int32; external 'NICAIU.DLL';

Ja, da möchte ich nochmal nachfragen: ist in der oben gezeigten Deklaration PChar gleich array of PChar? Das würde sinnvoll erscheinen. Bei bestimmten Funktionen aus der WinAPI ist das so, nun weiß ich nicht, ob das allgemein in Delphi gilt.

Grüße, Messie

Apollonius 23. Mär 2009 19:31

Re: Kann eine Typdeklaration eine Anweisung erhalten?
 
const char [] ist ein Array of AnsiChar mit unbekannter Länge, vermutlich also ein PAnsiChar. Array of PChar ist garantiert falsch. Beim zweiten Parameter kann entweder explizit ein Zeiger übergeben werden oder es wird var verwendet. Außerdem musst du noch mit der Aufrufkonvention aufpassen.

quendolineDD 23. Mär 2009 19:33

Re: Kann eine Typdeklaration eine Anweisung erhalten?
 
Delphi-Quellcode:
type
PTaskHandle = ^TTaskhandle;

function DAQmxCreateTask(const taskname : array of Char; taskhandle : PTaskHandle) : Int32;
Bleibe lieber mit der Deklination der Typen so nah wie möglich am Original, um dir etwaiges Fehlverhalten zu ersparen.

Edit: Auch bei so wenigen Wörtern kann man sich doch imens vertippen :p

thkerkmann 23. Mär 2009 19:49

Re: Kann eine Typdeklaration eine Anweisung erhalten?
 
Hi
Delphi-Quellcode:
function DAQmxCreateTask(taskname : PChar; var taskhandle : TaskHandle) : Int32;
würde ich verwenden.

Im Original heisst es const char tastkname[], was zeigt dass ein Pointer übergeben wird, wobei die Daten auf die er zeigt nicht verändert werden sollen.
taskhandle dagegen ist ein Rückgabewert und sollte als var deklariert werden. Damit wird automatisch ebenfalls ein Pointer auf diese Variable übergeben.

Ein string läßt sich dann einfach mit
Delphi-Quellcode:
var
  sTaskname: string;
  taskhandle: TaskHandle;
  ...
  sTaskname := 'meinetask';
  result := DAQmxCreateTask(pChar(sTaskname), taskhandle);
oder direkt
Delphi-Quellcode:
  result := DAQmxCreateTask('meinetask', taskhandle);
übergeben.

Wenn man sich mal die unit windows anschaut - sofern man den Quellcode hat - findet man dutzende dieser Beispiele.

Gruss

messie 24. Mär 2009 10:35

Typdeklarationen in C und Delphi
 
Ich habe TTaskHandle jetzt auch als Pointer bezeichnet, kommt dem Original void* doch am nächsten

Um jetzt keinen neuen Thread eröffen zu müssen:

Was ist denn bitte
Zitat:

typedef unsigned __int64
für ein Typ in Delphi? Denn cardinal endet ja bei 32 bit.

Grüße, Messie

himitsu 24. Mär 2009 12:41

Re: Kann eine Typdeklaration eine Anweisung erhalten?
 
Statt einem PAnsiChar kann man sogar einen AnsiString verwenden, da dessen interner Zeiger auf den Textanfang und nicht auf den Anfang der String-Struktur zeigt und am Ende sogar eine #0 angehängt ist. :angel:
Also solange der "String" nicht in der Funktion verändert wird.
Delphi-Quellcode:
function DAQmxCreateTask(const taskname: AnsiString; var taskhandle: TTaskHandle): LongInt;

Zoot 24. Mär 2009 12:53

Re: Typdeklarationen in C und Delphi
 
Zitat:

Zitat von messie
Was ist denn bitte
Zitat:

typedef unsigned __int64
für ein Typ in Delphi? Denn cardinal endet ja bei 32 bit.

Grüße, Messie

UInt64.

messie 24. Mär 2009 12:58

Re: Typdeklarationen in C und Delphi
 
Zitat:

Zitat von Zoot
Zitat:

Zitat von messie
Was ist denn bitte
Zitat:

typedef unsigned __int64
für ein Typ in Delphi? Denn cardinal endet ja bei 32 bit.

Grüße, Messie

UInt64.

Wieso kennt mein Delphi das nicht? Wo ist denn der Typ deklariert?

Grüße, Messie

Zoot 24. Mär 2009 13:05

Re: Typdeklarationen in C und Delphi
 
Zitat:

Zitat von messie
Wieso kennt mein Delphi das nicht? Wo ist denn der Typ deklariert?

Ja, den gibts leider erst ab Delphi 7.
Deklariere dir doch irgendwas anderes mit 8 byte größe und konvertier es hinterher.

messie 24. Mär 2009 16:23

Re: Typdeklarationen in C und Delphi
 
Ich habe jetzt erstmal einen int64 genommen, vielleicht brauche ich den Wert garnicht.

Mit der dll kann ich jetzt sprechen. Nun muss ich die noch dazu bringen, das Richtige zu tun.

Aus
Code:
DAQmxReadAnalogF64(TaskHandle taskHandle, int32 numSampsPerChan, float64 timeout, bool32 fillMode, float64 readArray[], uInt32 arraySizeInSamps, int32 *sampsPerChanRead, bool32 *reserved);
habe ich
Delphi-Quellcode:
function DAQmxReadAnalogF64(taskHandle: PTaskHandle;
                            numSampsPerChan: INT32;timeout: FLOAT64;fillMode: BOOL32;var readArray: array of double;arraySizeInSamps: UINT32;var sampsPerChanRead: INT32;var reserved: BOOL32): INT32 cdecl
gemacht. Beim Aufruf
Delphi-Quellcode:
DAQmxReadAnalogF64(TaskHandle,1000,10.0,DAQmx_Val_GroupByChannel,data,1000,read,nil);
bekomme ich aber die Meldung "die Typen der tatsächlichen und formalen Parameter müssen übereinstimmen", da finde ich den Fehler nicht. Ich vermute mal, dass readArray[] und array of double nicht kompatibel sind weil c ja eigentlich keine offenen arrays kennt.
Wie gehe ich damit um?

Grüße, Messie

uligerhardt 24. Mär 2009 16:44

Re: Typdeklarationen in C und Delphi
 
Zitat:

Zitat von messie
Ich habe eine Headerdatei und eine c-lib, die per OLE auf die tatsächliche dll zugreift.

Schuss ins Blaue: Ich konnte nicht ganz rauslesen, welche Lib/DLL/... jetzt das OLE-Objekt ist, aber vielleicht kannst du ja direkt auf selbiges zugreifen, und etwaige Wrapper-Bibliotheken auslassen?

messie 24. Mär 2009 17:13

Re: Typdeklarationen in C und Delphi
 
Genau das versuche ich hier gerade, indem ich direkt auf die hinter den Wrapper liegende dll zugreife. Das funktioniert auch schon etwas, aber die Übersetzung der dll-Zugriffe klemmt etwas.

Grüße, Messie

uligerhardt 24. Mär 2009 19:47

Re: Typdeklarationen in C und Delphi
 
Zitat:

Zitat von messie
Genau das versuche ich hier gerade, indem ich direkt auf die hinter den Wrapper liegende dll zugreife.

Ach so. Dann nur weiter so. :mrgreen:

Uwe Raabe 24. Mär 2009 20:36

Re: Typdeklarationen in C und Delphi
 
Zitat:

Zitat von messie
Aus
Code:
DAQmxReadAnalogF64(TaskHandle taskHandle, int32 numSampsPerChan, float64 timeout, bool32 fillMode, float64 readArray[], uInt32 arraySizeInSamps, int32 *sampsPerChanRead, bool32 *reserved);
habe ich
Delphi-Quellcode:
function DAQmxReadAnalogF64(taskHandle: PTaskHandle;
                            numSampsPerChan: INT32;timeout: FLOAT64;fillMode: BOOL32;var readArray: array of double;arraySizeInSamps: UINT32;var sampsPerChanRead: INT32;var reserved: BOOL32): INT32 cdecl
gemacht. Beim Aufruf
Delphi-Quellcode:
DAQmxReadAnalogF64(TaskHandle,1000,10.0,DAQmx_Val_GroupByChannel,data,1000,read,nil);
bekomme ich aber die Meldung "die Typen der tatsächlichen und formalen Parameter müssen übereinstimmen", da finde ich den Fehler nicht. Ich vermute mal, dass readArray[] und array of double nicht kompatibel sind weil c ja eigentlich keine offenen arrays kennt.

Da hast du vollkommen Recht! Aber bei dem Float-Array kannst du mogeln (machen die C-Programmierer dauernd):
Delphi-Quellcode:
function DAQmxReadAnalogF64(taskHandle: PTaskHandle;
                            numSampsPerChan: INT32;
                            timeout: FLOAT64;
                            fillMode: BOOL32;
                            var readArray: FLOAT64;
                            arraySizeInSamps: UINT32;
                            var sampsPerChanRead: INT32;
                            reserved: Pointer): INT32 cdecl;
...
  DAQmxReadAnalogF64(TaskHandle, 1000, 10.0, DAQmx_Val_GroupByChannel, data[0], 1000, read, nil);
...

Apollonius 24. Mär 2009 21:25

Re: Typdeklarationen in C und Delphi
 
Ein offenes Array wird als zwei Parameter übergeben: Zeiger zu den Daten und höchster Index (d.h. Länge - 1). Außerdem solltest du natürlich kein Var nehmen, wenn du dich für Arrays entscheidest.

himitsu 24. Mär 2009 21:34

Re: Typdeklarationen in C und Delphi
 
dein Delphi könnte eventuell Types.TDoubleDynArray schon kennen :angel:

messie 26. Mär 2009 09:53

Re: Typdeklarationen in C und Delphi
 
Zitat:

Zitat von Uwe Raabe
Aber bei dem Float-Array kannst du mogeln (machen die C-Programmierer dauernd):
Delphi-Quellcode:
function DAQmxReadAnalogF64(taskHandle: PTaskHandle;
                            numSampsPerChan: INT32;
                            timeout: FLOAT64;
                            fillMode: BOOL32;
                            var readArray: FLOAT64;
                            arraySizeInSamps: UINT32;
                            var sampsPerChanRead: INT32;
                            reserved: Pointer): INT32 cdecl;
...
  DAQmxReadAnalogF64(TaskHandle, 1000, 10.0, DAQmx_Val_GroupByChannel, data[0], 1000, read, nil);
...

Das hat nicht geklappt. Ich habe auch mal probehalber mit einem festen array versucht, geht auch schief.
data habe ich als array of FLOAT64 deklariert. Was mache ich da falsch?


Zitat:

Zitat von Apollonius
Außerdem solltest du natürlich kein Var nehmen, wenn du dich für Arrays entscheidest.

Ich habe mich nicht entschieden, sondern bekomme das so vorgegeben. Aber wo ist das problem mit dem array als var-Parameter? Ich hatte das schon häufiger.

Grüße, Messie

messie 26. Mär 2009 11:08

Re: Typdeklarationen in C und Delphi
 
Hmmm,

ich habe jetzt mal das nil durch eine cardinal-Variable mit Wert 0 ersetzt, damit läuft der Compiler durch. Beim Auslesen der Daten bekomme ich dann den Fehler
Zitat:

DAQmxErrorCAPIReservedParamNotNULL
.
Wie kann ich die Deklaration so anpassen, dass ich ein nil übergeben kann? Bool32 ist bisher ein cardinal (im C-Header ein uint32).

Grüße, Messie

Apollonius 26. Mär 2009 17:16

Re: Typdeklarationen in C und Delphi
 
Zitat:

Zitat von messie
Zitat:

Zitat von Apollonius
Außerdem solltest du natürlich kein Var nehmen, wenn du dich für Arrays entscheidest.

Ich habe mich nicht entschieden, sondern bekomme das so vorgegeben. Aber wo ist das problem mit dem array als var-Parameter? Ich hatte das schon häufiger.

Die C-Deklaration sieht eine einfache Indirektion vor. Mit var und dynamischem Array hast du aber eine doppelte Indirektion.

messie 31. Mär 2009 13:01

Re: Typdeklarationen in C und Delphi
 
So, mittlerweile habe ich das zum Laufen gebracht, wobei ich dem Beispiel von Uwe gefolgt bin.

Ich habe auch eine andere Routine benutzt, die das nil akzeptiert (und die ich auch besser verwenden kann).

Jetzt fehlt mir aber noch ein Teil der Deklaration, den Dr. Bob mit seinem Tool auch übersprungen hat bzw. der schrottig rüberkam:
Code:
#define DAQmx_Val_Bit_TermCfg_RSE (1<<0) // RSE terminal configuration
Was bedeutet das (ist das nicht eher ein Makro?) und wie kann ich das im Delphi implementieren?

Danke, Messie

uligerhardt 31. Mär 2009 13:28

Re: Typdeklarationen in C und Delphi
 
Zitat:

Zitat von messie
Code:
#define DAQmx_Val_Bit_TermCfg_RSE (1<<0) // RSE terminal configuration
Was bedeutet das (ist das nicht eher ein Makro?) und wie kann ich das im Delphi implementieren?

Das ist eher ;-) ein Makro und müsste wohl
Delphi-Quellcode:
const
  DAQmx_Val_Bit_TermCfg_RSE = 1 shl 0; // RSE terminal configuration
sein.


Alle Zeitangaben in WEZ +1. Es ist jetzt 14:56 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz