Entwickler-Ecke
Dateizugriff - Rockgabe eines Wertes per Pointer
Tactive - Sa 23.11.02 03:26
Titel: Rockgabe eines Wertes per Pointer
Hallo,
ich schreibe gerade unter C/C++ eine DLL die ich per Delphi benutzen möchte. Nun habe ich eine Funktion die per Pointer einen Wert zurückgeben soll.
In der C/C++ DLL sieht das so aus:
Quelltext
1: 2: 3: 4: 5:
| SAMLOAD_API bool SAM_CreateNewArchieve__1(DWORD *dwIDArchieve) { (*dwIDArchieve) = 45; return true; } // SAM_CreateNewArchieve |
In meinem Delphi Projekt habe ich in einer Klasse jetzt folgendes:
Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| type DWORDPTR = ^Longword;
type SAMLoad = class public function CreateNewArchieve(NewArchieveID: DWORDPTR) : boolean; end;
implementation
function SAMLoad.CreateNewArchieve; external 'samload.dll' name 'SAM_CreateNewArchieve__1'; |
Um das ganze nun zu testen habe ich in einer andere Klasse
folgende Aufruf:
Quelltext
1: 2: 3: 4: 5: 6: 7: 8:
| var tst : Longword; txt : String; begin Sam.CreateNewArchieve(@tst); txt := IntToStr(tst); ShowMessage(txt); end; |
Eigendlich müsste in 'txt' doch nun die 45 stehen, aber leider bekomme ich immer nur 1 als Ergebnis. Was mache ich falsch ??
[/code]
tommie-lie - Sa 23.11.02 13:29
wenn das der Code aus deinem Programm ist, könnte folgendes der Fehler sein:
du shcreibst in der Deklaration:
Quelltext
1:
| function CreateNewArchieve(NewArchieveID: DWORDPTR) : boolean; |
aber in der Implementation dieser Funktion nur
Quelltext
1:
| function SAMLoad.CreateNewArchieve; |
Fazit: Es gibt eine deklarierte Funktion, die nirgendswo implementiert ist. Zusätzlich gibt es eien implementierte Funktion, die nirgendswo deklariert ist. Normalerweise sollte Delphi dir das gleiche Erzählen, wieich gerade, aber falls nicht, probier's mal so:
Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| type DWORDPTR = ^Longword;
type SAMLoad = class public function CreateNewArchieve(NewArchieveID: DWORDPTR) : boolean; end;
implementation
function CreateNewArchieve(NewArchieveID: DWORDPTR) : boolean; external 'samload.dll' name 'SAM_CreateNewArchieve__1'; |
Jetzt müsste es funktionieren.
Ach ja, du sparst dir eine Variable, wenn du in deiner anderen Klasse "zum testen" folgendes machst:
Quelltext
1: 2:
| Sam.CreateNewArchieve(@tst); Showmessage(IntToStr(tst)); |
Schon kannst du dir txt sparen...
Ob der C++-Teil Fehler enthält, weiß ich mangels C-Wissen nicht. :-(
wulfskin - Sa 23.11.02 15:08
Hallo Tactive!
Ich kenne mich mit C auch nicht aus, aber soweit ich weiss, ist es wichtig das man bei der Funktiondeklaration ein
stdcall anhängt. Versuch's mal so:
Quelltext
1: 2:
| function SAMLoad.CreateNewArchieve; external 'samload.dll' name 'SAM_CreateNewArchieve__1'; stdcall; |
Gruß wulfskin!
Tactive - Mo 25.11.02 01:20
Vielen Dank für Eure Hilfe aber klappt leider beides nicht. Wenn ich das mit dem 'stdcall' einbaue dann schmiert mir das Programm sogar mit einer Fehlermeldung ab. Verstehe das alles auch irgendwie nicht.
Muss aber dazu sagen das ich erst seit kurzem mit Delphi programmiere. Habe mich die letzten 2-3 Jahre mit C/C++ beschäftigt.
Delete - Mo 25.11.02 11:56
wulfskin hat folgendes geschrieben: |
... aber soweit ich weiss, ist es wichtig das man bei der Funktiondeklaration ein stdcall anhängt. |
Tactive hat folgendes geschrieben: |
Wenn ich das mit dem 'stdcall' einbaue dann schmiert mir das Programm sogar mit einer Fehlermeldung ab. |
Ich empfehle zu dem Thema das
DLL-Tutorial [
http://assarbad.org/de/sources.shtml#News] von Assarbad:
Zitat: |
Das enthaltene Beispielprogramm zeigt einmal kurz, wie es sich auswirken kann, wenn man die Aufrufkonventionen nicht beachtet. Einfach mal etwas rumspielen, aber bitte beachten, daß unter Windows 9x durchaus ein Systemabsturz anstehen könnte ... |
Wenn ich mir die typische Arbeit des Assistenten vom VS6 ansehe, dann wird dort wie folgt deklariert:
Quelltext
1:
| #define SAMLOAD_API __declspec(dllexport) |
Die Namensähnlichkeit verleitet mich zu der Annahme, dass als Aufrufkonvention hier nicht
stdcall sondern vielleicht eher
cdecl verwendet werden müsste. Aber ich kann mich auch irren. Nur, meine Annahme würde auch dem Zitat aus Assarbads Tutorial entsprechen: wenn ich die Aufrufkonvention nicht beachte, kann das Programm oder sogar das System abstürzen.
So, jetzt aber -
Brauchst du unbedingt eine Klasse für die Funktion? Ausgehend von einem ähnlichen Beispiel aus dem PSDK und der Borland-Übersetzung nach Delphi hätte ich folgendes vorgeschlagen:
Quelltext
1: 2:
| function CreateNewArchieve(out NewArchieveId: cardinal): boolean; external 'samload' name 'SAM_CreateNewArchieve__1'; |
Ich hätt´s gern ausprobiert und dir lieber ein erfolgreiches Posting geschrieben, aber - ich habe heute spaßeshalber meine allererste DLL mit dem Visual Studio 6 erstellt. Nur, als ich sie in Delphi verwenden wollte, erschien die unschöne Meldung:
Zitat: |
Die Datei XY ist verknüpft mit dem fehlenden Export ABC |
Obwohl ich eine Standard-DLL benutzt habe, die der Assistent vom VS6 bereits mit einer Beispielfunktion versehen hatte. :cry:
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!