Einzelnen Beitrag anzeigen

blackdrake

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

Fragen zur API-Entwicklung

  Alt 23. Aug 2011, 23:16
Hallo zusammen,

ich möchte gerne eine kleine API entwickeln und möchte gerne alles richtig und sauber machen und frage daher hier um Hinweise. Wert legen möchte ich auch auf gute Verträglichkeit mit C/C++ (z.B. Nutzung von C-Strings anstelle von PASCAL-Strings).

Ich habe hierfür 3 Fragen:


1) Redundanter Code bei den API "Headers"

Bei C ist es üblich, Header (*.h) und Code (*.c) in zwei Dateien zu trennen. In Delphi hat man hierfür 2 Abschnitte in einer einzigen PAS Datei. Ich habe gemerkt, dass durch diese Praxis große Teile des Codes redundant sind und ich diese immer synchron halten muss.

Als Beispiel erstelle ich eine DLL "MyDLL" mit einer Funktion "MyFunction", die ein record/struct "TMyType" zurückliefert. Ich muss den jenigen, die meine DLL nutzen wollen, die Deklaration von "TMyType" zur Verfügung stellen. Problematisch ist, dass ich bei der Entwicklung der DLL diesen TMyType definieren muss, allerdings auch bei der Nutzung.

- Entwicklung der DLL -

Datei MyDLL.dpr:
Delphi-Quellcode:
library MyDLL;

uses
  MyAPI1 in 'MyAPI1.pas';

function MyFunction: TMyType; cdecl;
begin
  // ...
end;

exports
  MyFunction;

end.
Datei MyAPI1.pas:
Delphi-Quellcode:
unit MyAPI1;

interface

type
  // REDUNDANTER CODE :-(
  TMyType = record
    zahl: Cardinal;
    string: PAnsiChar;
  end

implementation

end.
- Nutzung der DLL -

Datei MyProgram.dpr:
Delphi-Quellcode:
program MyProgram;

uses
  MyAPI2 in 'MyAPI2.pas';

begin
  MyFunction; // auf die DLL wird zugegriffen
end.
Datei MyAPI2.pas:
Delphi-Quellcode:
unit MyAPI2;

interface

type
  // REDUNDANTER CODE :-(
  TMyType = record
    zahl: Cardinal;
    string: PAnsiChar;
  end

{$EXTERNALSYM MyFunction}
function MyFunction: TMyType; cdecl;

implementation

function MyFunction; external 'MyDll.dllname 'MyFunction';

end.

Hier wird deutlich, dass MyAPI1.pas und MyAPI2.pas die SELBEN Inhalte haben, mit Unterschied dass MyAPI2.pas (zur Benutzung der DLL) zusätzlich noch die Importe zur Verfügung stellt.

Wie kann ich verhindern, dass MyAPI1.pas ("Entwickler-Deklarationen") und MyAPI2.pas ("Benutzer-Deklarationen") so extreme Coderedundanzen aufweisen? (Ich wünschte, Delphi hätte so eine interface/implementation Trennung wie in C...)

(FYI: Ich entwickle die API gleichzeitig zu einer Client-Applikation, die diese DLL/API nutzt. Daher habe ich das unmittelbar das Problem, MyAPI1.pas und MyAPI2.pas ständig per Copy-Paste synchron zu halten, was keine gute Programmierpraxis sein kann...)


2) C++ Interoperatibilität

Sollte ich, wenn ich einfache Handhabung/Kompatibilität mit C/C++ wünsche, "cdecl" oder "stdcall" nutzen?

Sollte ich "packed record" oder "record" nutzen, damit es mit "struct" am besten Kompatibel ist?


3) Versionsinfo: Sprachneutralität

Ich nutze Turbo Delphi (da ich OpenSource entwickle) und habe festgestellt, dass jede DLL mit der Locality "DE-DE" erstellt wird. Es scheint keine Möglichkeit zu geben, die VersionsInfo auf "Sprachneutral" (VALUE "Translation", 0x0000 0x04E4) anstelle "Deutsch (Deutschland)" (VALUE "Translation", 0x0407 0x04E4) umzustellen. Sobald ich die *.res in einem ResourceEditor auf 0000/04E4 ändere, erkennt Delphi die Versionsinformation nicht mehr an. Es wäre schon schön, wenn die DLL als Sprachneutral dargestellt würde, denn sie stellt in keinster Form eine GUI oder Dialoge zur Verfügung.


Ich freue mich über Antworten und Hinweise um die Best-Practise für API-Entwicklung unter Delphi zu finden.

Gruß
Daniel Marschall
Daniel Marschall

Geändert von blackdrake (24. Aug 2011 um 15:30 Uhr) Grund: [delphi]-tag anstelle [code]
  Mit Zitat antworten Zitat