Einzelnen Beitrag anzeigen

blackdrake

Registriert seit: 21. Aug 2003
Ort: Bammental
618 Beiträge
 
Delphi 10.3 Rio
 
#8

AW: Fragen zur API-Entwicklung

  Alt 28. Aug 2011, 05:02
Die Lösungen haben leider doch nicht funktioniert.

Meine vorherige Lösung hatte den Schwachpunkt, dass man im Anwendungsfall "MyAPI.pas" (für Funktionen) UND "MyAPI_H" (für Typen) einbinden muss. Das ist eine Unit zu viel. Im Gegensatz zu C scheint Delphi sehr unflexibel zu sein, da die Implementierung immer an das Interface gekoppelt ist...

Die Include-Lösung ist noch katastrophaler. Delphi prüft nämlich zuerst die Funktionen und bindet danach erst die Include ein. Er sagt also, dass er "TMyRecord" bei "function x: TMyRecord" nicht kennt, obwohl der Typ in der Include-Datei drin steht. Schreibt man vor dem {$I} noch ein "type", kommt Delphi ebenfalls durcheinander weil es zu Syntaxfehlern kommt. (Die Include enthält types und consts)...

Ich habe nach extrem langer Zeit die Lösung gefunden:


Die Unit MyAPI.pas enthält alles was benötigt wird. Alle Typen sowie die DLL-Importe. Diese PAS wird im Anwendungsfall verwendet - logisch.

Für die DLL-Entwicklung wird MyAPI_Impl.pas entworfen. Es use'd die MyAPI.pas . Anschließend werden die Funktionen, die vorher aus der DLL importiert wurden nochmal definiert und implementiert. Aus irgendeinem Grund meckert Delphi NICHT wegen einer doppelten Deklaration!!! (Stand: Turbo Delphi, unbekannt ob Verhalten auch in Delphi 7)

Durch das Smart-Linking wird die DLL auch nicht sich selbst importieren (Import Table), da auf die Import-Funktionen nicht zugegriffen wird. Stattdessen werden die Funktionen exportiert, die implementiert wurden.

Kurz: Bei der API-Entwicklung importiert man die Funktionen _UND_ implementiert sie nochmal. Delphi "entscheidet" sich dann für die Implementierung und gibt keinen Konflikt aus; auch kein overload ist nötig.




Delphi-Quellcode:
unit MyAPI;

interface

type
  TMyRecord = record
    foo: PAnsiChar;
  end;

function myfunc: TMyRecord; stdcall;

implementation

// Die DLL importiert sich dank Smart-Linking nicht selbst
function myfunc: TMyRecord; stdcall; external 'MyDLL.dllname 'myfunc';

end.
---

Delphi-Quellcode:
unit MyAPI_Impl;

interface

uses
  MyAPI;

// Seltsam, seltsam... Kein Namenskonflikt mit MyAPI.myfunc (imported)!
function myfunc: TMyRecord; stdcall;

implementation

function myfunc: TMyRecord;
begin
  result.foo := 'bar';
end;

end.
---

Delphi-Quellcode:
library MyDLL;

uses
  MyAPI_Impl in 'MyAPI_Impl.pas';

exports
  myfunc;

begin
end.
---

Delphi-Quellcode:
program MyProg;

uses
  MyAPI in 'MyAPI.pas';

var
  x: TMyRecord;

begin
  x := myfunc;
end.

Es ist seltsam, dass dieses merkwürdige Verhalten (Symbolkonflikt, der keiner ist) nicht dokumentiert ist. Auch ist es seltsam, dass noch niemand zuvor das Problem der Coderedundanz bei DLL-Entwicklung mit gleichzeitiger Nutzung gestoßen ist.


===> Kann bitte jemand bestätigen, dass dieses Verhalten auch in Delphi 6 und 7 existiert? Ich möchte den Code wegen OpenSource gerne bis mindestens D6 kompatibel halten.






Offen sind noch meine Fragen 2 und 3. Weiß denn niemand Rat?


Gruß
Daniel Marschall
Daniel Marschall
  Mit Zitat antworten Zitat