Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Zwei DLLs statisch laden (https://www.delphipraxis.net/210076-zwei-dlls-statisch-laden.html)

TSchnuckenbock 25. Feb 2022 16:48

Zwei DLLs statisch laden
 
Der Hersteller eines externen Gerätes hat seine API angepasst. In dieser API ist die Kommunikation zum Gerät via Netzwerk gekapselt.
Der Hersteller hat ein SDK mitgeliefert, in dem ein Demo-Projekt in C++ (Visual Studio) enthalten ist mit den entsprechenden Header-Dateien und den *.lib-Dateien. (die Visual-Studio-Demo krieg ich aktuell aber nicht erzeugt....früher bei einer älteren API-Version hatte ich das aber mal am Laufen)
Zusätzlich gibt es die DLLs, damit man die Funktionen auch anderweitig nutzen kann.
Auch ein Simulator als „exe“ ist vorhanden um ohne externes Gerät entwickeln zu können.

In früheren API-Versionen war es eine DLL, die benötigt wurde. In der neuen API sind die Funktionen nun in zwei DLLs aufgesplittet (und um weitere Funktionen ergänzt worden).

Ich beschränke mich jetzt auf drei Funktionen: Connect, Disconnect und DoSomehting.
Die haben sich im Laufe der API-Versionen nicht geändert (Name und Parameter immer gleich).

Früher waren alle Funktionen in der einen „Lib_Old.dll“.

Nun sind Connect und Disconnect in „Lib_A.dll“ und die DoSomething in der „Lib_B.dll“.

Das statische Laden der DLL in früheren APIs hat bisher geklappt. Nur jetzt mit zwei DLLs klappt es nicht.

Der Code sieht prinzipiell so aus:

Delphi-Quellcode:
unit uUnit_Bsdp_DelphiPraxis;

interface

const

  LIB_A = 'Lib_A.dll';
  LIB_B = 'Lib_B.dll';

  LIB_OLD = 'Lib_Old.dll';

   // Rückgabewerte:
   //   0: OK
   // > 0: Fehlercode
  function api_Connect(IPAddress: PAnsiChar; var ClientHandle: Integer): Integer; cdecl; external LIB_A;
  function api_Disconnect(ClientHandle: Integer): Integer; cdecl; external LIB_A;

  function api_DoSomething(ClientHandle: Integer): Integer; cdecl; external LIB_B;


implementation

end.
Beim Connect wird ein ClientHandle generiert, was man dann zurückbekommt, um damit dann zukünftig alle Funktionen aufzurufen. Das ist immer „1“.

Problem ist, daß Connect und Disconnect aus der „Lib_A.dll“ funktionieren, aber das DoSometing aus der „Lin_B.dll“ nicht.
Nehme ich im obigen Code jeweils hinter dem external „Lib_Old.dll“, lade also alle drei Funktionen aus der DLL einer älteren API, dann macht der Simulator brav alles, was er soll.

Jetzt hätte ich ja gedacht, daß ich mir nur die DoSomething aus der älteren „Lib_Old.dll“ hole und Connect und Disconnect aus der „Lib_A.dll“ und alles müßte funktionieren.
Tut‘s aber nicht. Connect und Disconnect funktionieren, aber die DoSomething wieder nicht.
Als Rückgabewert bekomme ich ürbigens den Fehlercode „Invalid ClientHandle“.

Ausprobiert hatte ich auch StdCall statt cdecl bei der DoSomething......hilft aber auch nichts.

Muß man irgendwas beachten, beim Laden mehrerer DLLs?
Mit „Index“ hatte ich auch schon fruchtlos rumprobiert.

Hat irgendwer eine zündende Idee, wo ich jetzt noch ansetzen könnte?

Ein Projekt mit dynamischen Laden hatte ich auch probiert, aber mit dem selben Ergebnis.

Uwe Raabe 25. Feb 2022 17:08

AW: Zwei DLLs statisch laden
 
Es ist vollkommen egal ob ein oder zwei DLLs - das Verfahren ist immer gleich. Eventuell hat sich die Deklaration der Funktion in der neuen DLL doch geändert.

TSchnuckenbock 25. Feb 2022 17:15

AW: Zwei DLLs statisch laden
 
Ich hatte ja probiert, alle drei Funktionen aus der alten DLL zu laden und da klappts, sowohl was der Simulator macht, wie auch jeweils korrekter Rückgabewert 0. Hätte sich die Deklaration geändert, dann hätte es eine Fehlermeldung mit dem neuen Simulator geben müssen.

dummzeuch 25. Feb 2022 17:16

AW: Zwei DLLs statisch laden
 
Ich tippe genau wie Uwe ganz stark darauf, dass die Deklarationen sich irgendwie geändert haben. Ob eine oder zwei DLLs ist dabei völlig egal.

Überprüfe mal anhand der C-Header:
  • Parameter-Typen
  • Parameter-Reihenfolge
  • Calling Convention

Mögliche Ursache:

In C/C++ bastlen sich die Leute bei Interface-Änderungen gerne einen "Compatibility-Layer" mit #define-Makros. Wenn man da nicht genau hinschaut, sucht man sich dumm und dusselig.

Sinspin 25. Feb 2022 17:56

AW: Zwei DLLs statisch laden
 
Ist die API so extrem Geheim dass Du nichtmal die Header Dateien oder das C/C++ Beispielprojekt mit uns teilen kannst? Denn aktuell ist es nur Rätselraten.

TSchnuckenbock 25. Feb 2022 18:06

AW: Zwei DLLs statisch laden
 
Ja, die ist so geheim. Das verlangt der Hersteller. Da es eine ganz kleine Nische ist, werden es auch nur ganz wenige Kunden sein (eine Hand voll?), die das SDK überhaupt bekommen. Der Hersteller läßt sich das auch üppigst bezahlen.

Wenn ich die Deklaration der Funktionen aus den C++-Headern 1:1 neu gegen alt in einem Texteditor untereinander packe, dann ist da absolut kein Unterschied.

Es ist auch so, daß alle Funktionen aus der zweiten DLL nicht gehen.

Ich werd mir morgen mal das C++-Demo-Projekt zu Gemüte führen und gucken, ob ich das zum Laufen krieg. Da sind aber meiner Erinnerung nach die *.lib eingebunden und nicht die DLLs.

Sinspin 25. Feb 2022 18:18

AW: Zwei DLLs statisch laden
 
Wenn das so teuer ist dann sollten die mal Sourcecode rausrücken der die DLLs verwendet. Der kann ja auch in C/C++ sein. Aber dann kann man sehen was zu machen ist.
Allerdings, ich habe auch schon *.lib direkt in Delphi (32 Bit) eingebunden und verwendet. Mal gucken wo das Programm ist. Ist nicht Geheim, kann ich also Posten ;-)

TSchnuckenbock 25. Feb 2022 19:14

AW: Zwei DLLs statisch laden
 
Ich habe inzwischen die Vermutung, daß der Fehler nicht beim Laden der DLLs liegt, sondern daß intern in den Funktionen ein Check gemacht wird, aus welcher API sie sind. Das geht dann an den Simulator und der sagt "Nein", will ich nicht und haut den Fehler "falsches ClientHandle" raus.
Sowas in der Art. Das würde erklären, daß mit meinem Konstrukt und Laden aller Funktion aus der alten DLL alles geht, aber wenn ich die aufgespaltenen nutze, dann gehen die Funktionen aus der Lib_A, aber die Funktionen aus Lib_B nicht, weil der Programmierer der DLLs z.B. den Fehler gemacht hat, in LIB_B den API-Versions-Code nicht richtig angepasst zu haben auf die neue API.

Ich könnte mir vorstellen, daß ich eventuell sogar der einzige bin, für den es die DLLs gibt....die anderen Nutzer/Kunden schreiben ihren Krams vermutlich auch in C++ und nutzen die *lib.

Ich werd' mich wohl mal an den Hersteller wenden und dem das Problem schildern. Mal sehen wie ich das Problem rüber kriege....english for me and the manufactura is foreign. ;-)

@Sinspin: Aber ein Beispiel-Code mit *lib fände ich trotzdem gut, falls du finden solltest.

shebang 27. Feb 2022 11:18

AW: Zwei DLLs statisch laden
 
Hast du dir die DLLs mal mit dem Dependency Walker angeschaut? Vielleicht gibt der irgendwelche hilfreichen Hinweise auf die Ursache deines Problems.

Sinspin 27. Feb 2022 18:33

AW: Zwei DLLs statisch laden
 
Hallo,

ich finde meine alten Delphi Quelltexte nicht.
Was ich aber gefunden habe ist ein wrapper. Via MS Visual Studio habe ich mir selber eine DLL aus der .lib gemacht.

Wenn Du jetzt zwei .lib hast wäre es eventuell eine Idee die wieder in eine dll draus zu machen.

Allerdings, bei dem von dir beschriebenen Preis würde ich erstmal beim Hersteller anklopfen und fragen ob der helfen kann.

TSchnuckenbock 27. Feb 2022 20:23

AW: Zwei DLLs statisch laden
 
Mit dem Dependency Walker hatte ich schon geschaut.

Ich denke, ich bau dem Hersteller morgen mal ein kleines Demonstrationsprojekt mit Lazarus (in Delphi hab' ich das ja schon).
Dann soll der sich mal äußern.

Ich vermute, der Fehler bzw. das Problem steckt in den DLLs.

Erstmal Danke.

Vielleicht führe ich mir auch mal Rudy Velthuis Seite etwas intensiver zu Gemüte:

http://rvelthuis.de/articles/articles-cobjs.html

jaenicke 28. Feb 2022 06:51

AW: Zwei DLLs statisch laden
 
Zitat:

Zitat von TSchnuckenbock (Beitrag 1502776)
Ich denke, ich bau dem Hersteller morgen mal ein kleines Demonstrationsprojekt mit Lazarus (in Delphi hab' ich das ja schon).
Dann soll der sich mal äußern.

Vielleicht wäre es erfolgversprechender, wenn du eins in C++ erstellst, das nicht die .lib Dateien, sondern die .dll Dateien verwendest. Das sollte ja vom Ablauf her identisch sein. Wenn der Hersteller hauptsächlich mit C++ arbeitet, wäre das den Entwicklern dort vermutlich am liebsten und damit am zielführendsten.

TSchnuckenbock 28. Feb 2022 19:59

AW: Zwei DLLs statisch laden
 
So, ich hab' mir heute ein C++-Projekt zusammengepopelt (C/C++ ist ja nicht unbedingt mein täglich Brot), in dem die Dlls und die Libs eingebunden sind.

So wie ich es im Debugger eben gesehen habe, scheint es dasselbe Problem zu geben.

Morgen ist ein neuer Tag. Vielleicht probier ich auch das Demo-Projekt des Herstellers mal zum Laufen zu bringen. Hab' mich ja jetzt mal wieder etwas mit C++ auseinandergesetzt.....

TSchnuckenbock 3. Mär 2022 07:15

AW: Zwei DLLs statisch laden
 
Update: Ich hatte inzwischen auch das Demo-Projekt in C++ vom Hersteller zum Laufen bekommen. Das war OK, aber da sind die *.lib verwendet und nicht die DLLs.

Dann dem Hersteller das Problem mitgeteilt und so wie es ausschaut, hat der zuständige Entwickler die Probleme mit den DLLs nun auch feststellen können. Er arbeitet daran, das Problem zu beheben.

TSchnuckenbock 4. Mär 2022 10:54

AW: Zwei DLLs statisch laden
 
Update: Ich habe vom Hersteller ein angepasstes SDK bekommen. So wie es auf den ersten Blick den Eindruck macht, funktionieren nun alle Funktionen, auch diejenigen, die Strukturen/Records zurückliefern.

Der Fehler lag also nicht in meinem Einflussbereich und der Hersteller hat auch fix reagiert.

Vielen Dank an alle, die sich bemüht haben, den Fehler einzukreisen.

Ich denke, das Thema ist damit erledigt.

Gruß aus dem Land der Schnucken.


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:57 Uhr.

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