Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Header von C nach Delphi


GuaAck - Mo 03.02.14 23:15
Titel: Header von C nach Delphi
Liebe Experten,

ich möchte im Delphi eine in Standard-C defnierte DLL nutzen. So etwas habe ich schon gemacht, aber bei der Syntax der folgenden Header-Datei in C komme ich mit meinem Basiswissen in C nicht weiter:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
// C-Code
// ========
// typedef enum  {fmiOK, fmiWarning, fmiDiscard, fmiError, fmiFatal} fmiStatus;
// typedef void  ( *fmiCallbackLogger)        (fmiComponent c, fmiString instanceName, fmiStatus status,
//                                             fmiString category, fmiString message, ...);
// typedef void* ( *fmiCallbackAllocateMemory)(size_t nobj, const size_t size);
// typedef void  ( *fmiCallbackFreeMemory)    (void* obj);
//
// typedef struct {
//     fmiCallbackLogger         logger;
//     fmiCallbackAllocateMemory allocateMemory;
//     fmiCallbackFreeMemory     freeMemory;
//   } miCallbackFunctions;

// Übersetzung Delphi; hier nicht angeführte Typen sind elementare Delphi-Typen wie Integer, Pointer usw.
// ========
 TYPE
  fmiStatus = (fmiOK,fmiWarning,fmiDiscard,fmiError,fmiFatal);

  fmiCallbackLogger = PROCEDURE(VAR c: fmiComponent; VAR instanceName: fmiString; VAR status: fmistatus;
    VAR category: fmiString; VAR messagex: fmiString) OF OBJECTcdecl;
  fmiCallbackAllocateMemory = PROCEDURE(VAR nobj: size_t; Size: size_t) OF OBJECTcdecl;
  fmiCallbackFreeMemory = PROCEDURE(obj: Pointer) OF OBJECT;  cdecl;

  fmiCallbackFunctions = RECORD
    logger: fmiCallbackLogger;
    allocateMemory: fmiCallbackAllocateMemory;
    freeMemory: fmiCallbackFreeMemory;
  END;


Der Compiler ist zufrieden.
Unsicher bin ich bei der Parameterübergabe (wann Pointer auf den Stack, wann der ganze Inhalt; s.u. in dieser Rubrik). Besonders ist mir mit das Doppelstern-Konstrukt "typedef void* ( *fmiCallbackAllocateMemory)" unklar, ich würde ^PROCEDURE schreiben, was aber natürlich Unsinn ist.

Debuggen ist schwierig, mit Assembler komme ich leidlich zurecht. Aber der Instanziierung-Aufruf ist der komplexeste von alle Funktionsaufrufen, und wenn der nicht geht, dann nützt der Debugger leider bei den einfachen anderen Funktionen nichts.

Umso mehr hoffe ich auf Hinweise.

Grüße
GuaAck


jaenicke - Di 04.02.14 09:47

of object ist 100%ig falsch. Methoden eines Objektes sind das im Original nicht.

Und von var-Parametern steht im Original auch nichts, die würdest du an dem * für einen Pointer erkennen.

cdecl ist natürlich möglich (EDIT: im Sinne von "könnte dort benutzt worden sein", du musst natürlich das gleiche nutzen), üblicher wäre aber stdcall.

Und ich würde die Typen in Delphi immer mit einem T vorne bezeichnen, einfach um in Delphi sauberen Quelltext zu haben.


Gammatester - Di 04.02.14 10:54

void * ist ein untypisierter pointer. Also etwa

Delphi-Quelltext
1:
2:
type
  TfmiCallbackAllocateMemory = function(nobj: size_t; Size: size_t): pointer; stdcall;
was ja auch irgendwie aus dem Namen analog AllocMem vervorgeht (allokiere mir nobj Teile der Größe size), und natürlich keine var parameter, wie schon von user profile iconjaenicke bemerkt.


GuaAck - Mi 05.02.14 23:15

Danke an beide,

das "of object" war mir bisher nicht wirklich klar, es funktionierte bei mir immer bei der Übergabe von Prodeduren/Functions (in meinen eigene Programmen.) Bei DLLs hatte ich noch nie mit Callback-Funktionen zu tun. Bei der Methode einer Klasse reicht es ja nicht aus, wie bei einer globalen Procedure die Adresse des Codes zu übergeben, es muss ja zusätzlich auch der Context übergeben werden.

cdecl war keine Frage, Standard-C war für die DLL spezifiziert. (klar, das dann auch "of object" sinnlos wäre, hatte ich aber nicht verstanden.)

Auch der * ist mir klarer geworden.

Jedenfalls, das Puzzle ist aufgegangen, Instanzieren mit Nutzung der CallBackfunktionen und Freigabe der Instanz gehen, der Rest ist harmlos. Und ich habe doch Einiges aus Euren "Puzzelsteinen" gelernt.

Danke also und beste Grüße
GuaAck