C DLL Funktion einbinden - eary binding vs. late binding

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
PeterS
Beiträge: 185
Registriert: So 22. Feb 2015, 11:36
OS, Lazarus, FPC: L 4.4
CPU-Target: win32, win64

C DLL Funktion einbinden - eary binding vs. late binding

Beitrag von PeterS »

Hallo,

ich verstehe noch nicht genau, warum der Compiler einen Unterschied macht
wenn ich eine Funktion aus einer DLL "early" oder "late" einbinde.

Folgendes Beispiel:

Code: Alles auswählen

int Pa_GetVersion( void );
Für early binding ist das hier deklariert

Code: Alles auswählen

function Pa_GetVersion(): cInt; cdecl; external LibName;
Damit funktioniert in Lazarus das hier (=> early binding), mit 32 bit Lazarus / 32 bit Compiler.

Code: Alles auswählen

  Result:= 'PA version int:   ' +IntToStr( Pa_GetVersion);

Für late binding ist das hier deklariert

Code: Alles auswählen

var Pa_GetVersion: function():cInt ; cdecl;
..

function Pa_Load( const libfilename:string):boolean;
..
          Pointer( Pa_GetVersion):= DynLibs.GetProcedureAddress( PA_Handle, pAnsiChar( 'Pa_GetVersion'));
Das heißt für mich, das Programm kennt (nach Aufruf von Pa_Load) die Adresse der Funktion in der externen C DLL.
Und auch den Ergebnis-Typ der Funktion, denn der ist ja deklariert als cInt. Oder ?

Damit funktioniert das hier aber nicht ..

Code: Alles auswählen

  Result:= 'PA version int:   ' +IntToStr( Pa_GetVersion);
und der Compiler meckert:

Error: Incompatible type for arg no. 1: Got "<procedure variable type of function:LongInt;CDecl>", expected "QWord"
sysstr.inc(861,10) Hint: Found declaration: IntToStr(QWord):AnsiString;
sysstr.inc(856,10) Hint: Found declaration: IntToStr(Int64):AnsiString;
sysstr.inc(850,10) Hint: Found declaration: IntToStr(LongInt):AnsiString;


Der Compiler ruft also IntToStr(QWord) auf statt IntToStr(LongInt) - und das geht natürlich nicht.
Eigentlich müßte der Compiler doch wissen daß function result von Pa_GetVersion = Typ cInt ist ??
Und daher IntToStr(LongInt) anwenden ?

PeterS
Beiträge: 185
Registriert: So 22. Feb 2015, 11:36
OS, Lazarus, FPC: L 4.4
CPU-Target: win32, win64

Re: C DLL Funktion einbinden - eary binding vs. late binding

Beitrag von PeterS »

Beim "Fehler" beschreiben habe ich es jetzt endlich selber herausgefunden. :roll:

Code: Alles auswählen

  Result:= 'PA version int:   ' +IntToStr( Pa_GetVersion);
ist nicht dasselbe wie

Code: Alles auswählen

  Result:= 'PA version int:   ' +IntToStr( Pa_GetVersion() );
:shock:

Mathias
Beiträge: 7142
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: C DLL Funktion einbinden - eary binding vs. late binding

Beitrag von Mathias »

Hast du auch Herausgefunden, wieso es verschiedene Werte gibt ?
Oder hast du einfach nur den Fehler gefunden ?
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

PeterS
Beiträge: 185
Registriert: So 22. Feb 2015, 11:36
OS, Lazarus, FPC: L 4.4
CPU-Target: win32, win64

Re: C DLL Funktion einbinden - eary binding vs. late binding

Beitrag von PeterS »

Mathias hat geschrieben: Fr 5. Dez 2025, 20:12 Hast du auch Herausgefunden, wieso es verschiedene Werte gibt ?
Oder hast du einfach nur den Fehler gefunden ?
Ich gehe davon aus daß das Programm mit "late binding" und dem folgenden Code ..

Code: Alles auswählen

  Result:= 'PA version int:   ' +IntToStr( Pa_GetVersion);
die Adresse der Funktion "Pa_GetVersion" anzeigt, aber nicht die Funktion aufruft.
Also die Adresse, die mit DynLibs.GetProcedureAddress() an die VAR Pa_GetVersion zugewiesen wurde
=>

Code: Alles auswählen

var Pa_GetVersion: function():cInt ; cdecl; 

Benutzeravatar
Zvoni
Beiträge: 494
Registriert: Fr 5. Jul 2024, 08:26
OS, Lazarus, FPC: Windoof 10 Pro (Laz/FPC fixes)
CPU-Target: 64Bit
Wohnort: BW

Re: C DLL Funktion einbinden - eary binding vs. late binding

Beitrag von Zvoni »

Ein weiterer Punkt für Überlegungen "Early vs. Late Binding"
1) Bei Early Binding bist du vollständig davon abhängig, dass der Pfad zu deiner Lib dem System bekannt ist
2) Bei Late Binding kannst du im Prinzip die Lib ablegen, wo du willst. Du musst nur den Pfad an LoadLibrary mitgeben.

1) Ist sinnvoll, wenn du auf System-Libs zugreifst, die definitiv am korrekten Platz existieren
2) Ist sinnvoll, wenn du auf "optionale" Libs zugreifen willst. (Libs, welche unter Umständen woanderst hin installiert wurden).
Hier kann dann auch ganz einfach geprüft werden, ob die Lib überhaupt auf dem System vorhanden ist
Ein System sie alle zu knechten, ein Code sie alle zu finden,
Eine IDE sie ins Dunkel zu treiben, und an das Framework ewig zu binden,
Im Lande Redmond, wo die Windows drohn.

PascalDragon
Beiträge: 1016
Registriert: Mi 3. Jun 2020, 07:18
OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
CPU-Target: Aarch64 bis Z80 ;)
Wohnort: München

Re: C DLL Funktion einbinden - eary binding vs. late binding

Beitrag von PascalDragon »

PeterS hat geschrieben: Fr 5. Dez 2025, 18:26 Beim "Fehler" beschreiben habe ich es jetzt endlich selber herausgefunden. :roll:

Code: Alles auswählen

  Result:= 'PA version int:   ' +IntToStr( Pa_GetVersion);
ist nicht dasselbe wie

Code: Alles auswählen

  Result:= 'PA version int:   ' +IntToStr( Pa_GetVersion() );
In den Nicht-Delphi Modi müssen parameterlose Routinenzeiger mit leeren Klammern aufgerufen werden, um zwischen einer Verwendung als Variable und einem Aufruf zu unterscheiden.
FPC Compiler Entwickler

Mathias
Beiträge: 7142
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: C DLL Funktion einbinden - eary binding vs. late binding

Beitrag von Mathias »

In den Nicht-Delphi Modi müssen parameterlose Routinenzeiger mit leeren Klammern aufgerufen werden, um zwischen einer Verwendung als Variable und einem Aufruf zu unterscheiden.
Dann interpretiert Delphi die immer als Funktions-Ergebnis, oder ist die umgekehrt ?
Bei Delphi muss man bei den Callproc auch kein @ machen.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

PascalDragon
Beiträge: 1016
Registriert: Mi 3. Jun 2020, 07:18
OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
CPU-Target: Aarch64 bis Z80 ;)
Wohnort: München

Re: C DLL Funktion einbinden - eary binding vs. late binding

Beitrag von PascalDragon »

Mathias hat geschrieben: Di 9. Dez 2025, 08:50
In den Nicht-Delphi Modi müssen parameterlose Routinenzeiger mit leeren Klammern aufgerufen werden, um zwischen einer Verwendung als Variable und einem Aufruf zu unterscheiden.
Dann interpretiert Delphi die immer als Funktions-Ergebnis, oder ist die umgekehrt ?
Bei Delphi muss man bei den Callproc auch kein @ machen.
Es kommt bei Delphi ein bisschen auf den Kontext an und es ist nicht wirklich dokumentiert. Deswegen sind die meisten Methodenzeiger in Delphi wohl procedure, um eben das Problem zu umgehen...
In mode Delphi versucht FPC sich da an die Regeln von Delphi zu halten, aber wir hatten da schon Bugfixes in der Vergangenheit, weil sich Delphi dann doch anders verhält als erwartet... :roll:
FPC Compiler Entwickler

Antworten