![]() |
aus c-Programm eine Delphi-dll aufrufen
hallo,
vielleicht kann mir ja jemand weiterhelfen. Mein Problem besteht darin, dass ich von einem c-Programm auf eine in delphi erstellte dll zugreifen möchte. Hier der delphi-code
Delphi-Quellcode:
library notiz;
uses SysUtils, Classes, ComObj, ActiveX, StdVcl, Windows, Messages, Variants, Graphics, Controls, Forms, Dialogs, AutoArchive_TLB, StdCtrls, Inifiles, ExtCtrls, uLogFile, uProgHilfe; {$R *.res} function anhaengen(dbID, docID, text: String): String; var test : String; sl_test : TStringList; Dms : HypDms; Notiz : IHypDocDosFile; begin CoInitialize(nil); ShowMessage(dbid+' '+docID+' '+text); ShowMessage('hallo1'); try Dms := CoHypDms.Create; ShowMessage('AA-Biblio initialisiert!'); except ShowMessage('Die AA-Biblio konnten nicht aktiviert werden!'); exit; end; ShowMessage('hallo2'); notiz:= IHypDocDosFile(Dms.OpenDocument(dbID, strtoint(docID))); ShowMessage('hallo3'); if (notiz <> nil) then begin ShowMessage('hallo4'); if notiz.ExistComponent('CC_TEXT', 1) then begin ShowMessage('hallo5'); test:= notiz.SaveComponentToString('CC_TEXT', 1); end; end else ShowMessage('hallo10'); notiz:= nil; CoUnInitialize; ShowMessage('ende'); end; exports anhaengen; begin end. und ich versuche nun von dem C-Programm aus darauf zuzugriefen und das funktioniert nicht. Der Teil in c sieht so aus: HMODULE handle; handle = LoadLibrary("notiz.dll"); if (handle != NULL) { //dies ist mit Sicherheit falsch definiert, da //das alles strings sind, die die dll erwartet und zurückgibt, //aber ich hab keine Ahnung, wie ich die umschreiben muss typedef int (*DLLFUNC)(char*, char*, char*); DLLFUNC func = (DLLFUNC)GetProcAddress(handle, "anhaengen"); if (func != NULL) { //das hier macht er nicht! int i = func("Test", "5512", "Test c_code"); } } FreeLibrary(handle); |
Re: aus c-Programm eine Delphi-dll aufrufen
1. Du musst statt Strings PChar nehmen (Das eentspricht dem *char in C
2. Du musst die Funktion mit "stdcall" definieren, damit alle Übergabe-Variablen aus dem Stack geholt werden (dort wo sie auch C hinschreibt). |
Re: aus c-Programm eine Delphi-dll aufrufen
danke, ich habe die Strings durch PChar ersetzt und das funktioniert auch soweit, dass die dll ihre Arbeit ordentlich tut. Die dll zeigt mir das als letztes an: ShowMessage('ende');
Danach kommt aber eine Fehlermeldung, mit der ich nichts anfangen kann: Debug Error File: i386\chkesp.c The Value of ESP was not properly saved across a function call. This is usually a Result of calling a function declared with one calling convention with a function pointer declared with a different calling convetion Was soll mir das sagen? |
Re: aus c-Programm eine Delphi-dll aufrufen
Ersetze das empfohlene stdcall in der Delphi DLL mit cdecl; und erstell es erneut.
/EDIT: Zur Erklärung: C verwendet per default (DLLFUNC) die Cdecl Aufufkonvention und nicht die StdCall. |
Re: aus c-Programm eine Delphi-dll aufrufen
vielen dank, jetzt funktioniert es!
|
Re: aus c-Programm eine Delphi-dll aufrufen
Zitat:
Edit: C will sich halt doch selber um seinen Stack-Pointer kümmern. |
Re: aus c-Programm eine Delphi-dll aufrufen
eine Frage hätte ich dann doch noch.
meine dll soll einen Rückgabewert an das c-programm zurückgeben (verkürzt dargestellt):
Delphi-Quellcode:
in meinem c-programm sieht das ja so aus:
library notiz;
uses SysUtils, ... {$R *.res} function anhaengen(dbID, docID, text: PChar): PChar; cdecl; var ... begin Result:= ''; if notiz.LoadComponentFromString(test , 'CC_TEXT', 1, true) then Result:='' else Result:='Error - laden der Komponente'; end; exports anhaengen; begin end. char i = func("Test", "5512", "Test c_code"); ich hätte jetzt angenommen, dass wenn kein Fehler in der dll war, wäre i jetzt leer und ansonsten würde da eben dieser Error-Text drin stehen. Das stand nun aber immer nur Zahlen drin z.B. mal -128. Wo liegt da noch das Problem? |
Re: aus c-Programm eine Delphi-dll aufrufen
Reicht es vielleicht auch, einfach einen Integerwert (als eine Art Fehlercode zu übergeben). Ist einfacher.
Oder fürs erste: Result:=PChar('Error'); |
Re: aus c-Programm eine Delphi-dll aufrufen
Versuch mal:
Code:
char i[80] = func("Test", "5512", "Test c_code");
|
Re: aus c-Programm eine Delphi-dll aufrufen
ok, dann eben als integer - danke
bei dem anderen bekomme ich folgende Fehlermeldung: 'char' kann nicht in 'char [80]' konvertiert werden |
Re: aus c-Programm eine Delphi-dll aufrufen
sollte es nicht so heißen:
Code:
Alle C-Stringverarbeitungs-Funktionen sollten mit beidem eigentlich klarkommen.
*char c = func(...);
//oder char[80] c = func(...); //da solltens dann aber auch 80 sein. |
Re: aus c-Programm eine Delphi-dll aufrufen
Bei der Rückgabe eines PChars liegt das Problem mit dem Speichermanager vor. Die DLL alloziiert den Speicher für den String, du gibst die Adresse dessen zurück - aber beim verlassen der Funktion verliert der String seine Gültigkeit und der Speichermanager gibt den Platz wieder frei. Dies geschieht bei den Vorschlägen mit dem konstanten Array für die Rückgabe als Empfangsplatz genauso wie bei dem Vorschlag von sirius, welcher sogar offensichtlich einen temporären TypeCast durchführt.
Abhilfe würde hier nur die Übergabe eines entsprechend grossen Buffers helfen beim Aufruf, in welchen dann die Funktion diesen Rückgabestring reinlegt, wenn er denn genügend groß ist. Mehr zu dem Thema hatte Luckie mal sehr schön zusammen gefaßt: ![]() |
Re: aus c-Programm eine Delphi-dll aufrufen
Dass ein Result(!=lokale Variable) seine Gültigkeit verliert, wär mir neu - könnte aber durchaus sein, bei dem ganzen rumgewurschtle zwischen C und Delphi ;-)
|
Re: aus c-Programm eine Delphi-dll aufrufen
Zitat:
Delphi-Quellcode:
Und hier verliert der String seine Gültigkeit mit verlassen der Procedure, da die Variable aus einer Adresse besteht (da Pointer), welche ihre Gültigkeit behält und im Register übergeben wird. Nur halt an der Adresse steht nix mehr.
// Result vom Typ PChar!
Result := 'hallo ballo'; Result := PChar('hallo ballo'); |
Re: aus c-Programm eine Delphi-dll aufrufen
danke.
Man muss es also explizit alloziieren? Reicht da Setlength? |
Re: aus c-Programm eine Delphi-dll aufrufen
Hängt davon ab, wo der String definiert ist, welchen du mit SetLength() setzt.
a) Wenn der String lokal innerhalb der Funktion deklariert ist, klappt dies nicht. b) wenn der String global in der DLL deklariert ist würde es klappen. Dann kannst du auch einen temporären PChar() Typecast machen für das Result, weil durch die globale Variable in der DLL verliert der erzeugte Zeiger auf den String Inhalt nicht seine Gültigkeit mit verlassen der Procedure. |
Re: aus c-Programm eine Delphi-dll aufrufen
Zitat:
Anders wäre der Fall, wenn man eine Variable übergebn will (z.B. vom Stack), da müsste man in der DLL mit getmem/stralloc arbeiten und im C dann wieder "free"-n. Edit: Oi, hier gabs ja schon eine Seite zwei. Den letzten Eintrag @Muetze hatt ich noch nicht gelesen. Aber genau der, trifft ja auf die Fragestellung zu. |
Re: aus c-Programm eine Delphi-dll aufrufen
Zitat:
|
Re: aus c-Programm eine Delphi-dll aufrufen
Zitat:
|
Re: aus c-Programm eine Delphi-dll aufrufen
Zitat:
|
Re: aus c-Programm eine Delphi-dll aufrufen
Ja das stimmt.
Man wird aber irgendwelche API Funktion (virtualalloc, virtualfree) finden. |
Re: aus c-Programm eine Delphi-dll aufrufen
es geht jetzt nochmal um die Übergabe der Parameter aus dem c-programm an die dll - das funktioniert irgendwie nicht so ganz
also, das c-programm übergibt in der Reihenfolge: dokumentennummer, archivnummer, notiztext in der dll kommt aber an: archivnummer, dokummentennummer, notiztext was kann ich da machen, das ist durcheinander, nicht mal von links nach rechts oder rechts nach links. was kann ich da machen? hat sich erledigt - war mein Fehler |
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:29 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