![]() |
WideString aus C++ DLL-Methode an Delphi-Host zurückgeben!?
Hallo Leute,
ich habe ein Problem beim Rückgabetyp "WideString" aus einer C bzw. C++ DLL heraus. Es besteht eine Delphi-Infrastruktur für Plugins, welche allerdings bisher ausschließlich auch mit Delphi-DLLs genutzt wurde. Nun hab ich vor diese auch mit C/C++-DLLs zu füttern. Geht so weit auch schonmal bei DLL-Methoden mit numerischen Rückgabe-Typen wie Integer und Bool und so weiter. Bsp (C++):
Delphi-Quellcode:
Sobal die in Delphi vorliegende Hostanwendung meine DLL lädt und die eben geschriebene Methode aufruft, geht das alles wunderbar so wie es sein soll.
bool DECLDIR EXTP_IsPlugIn( LPWSTR name )
{ return PlugIn.IsPlugIn( name ); } Im Parameter "name" steht entsprechend die erwartete GUID als String - das konnte ich mit dem VS-Debugger prüfen. Da ich nun hier und da schon gelesen habe, dass ein Delphi-WideString in C äquivalent mit einem LPWSTR ist, habe ich den Parametertyp auch so gewählt. Das heißt, in diese Richtung funktioniert die Übergabe. Außerdem Kommt auch das BOOL-True in der Hostanwendung an, da die innere Methode bislang immer True zurückliefert. Wenn ich nun aber eine Methode habe, die nach Anforderung im Delphi-Code einen WideString zurückliefern muss, so kommt absolut garnichts an - zum mindest sieht es aus wie ein leerer Sting "". Hier mal noch eine Methode, die einen WideString zurückliefern soll (C++):
Delphi-Quellcode:
Wie dem Code zu entnehmen ist, habe ich hier auch schon den Typ auf LPWSTR gesetzt. DECLDIR entsteht folgendermaßen (C++):
LPWSTR DECLDIR EXTP_GetPlugInDescription()
{ return PlugIn.GetPlugInDescription(); }
Delphi-Quellcode:
Nun stellt sich mir die Frage, wie ich wohl einen String aus C/C++ in eine für Delphi akzeptable WideString-Konforme Variante überführe.
#define DECLDIR __declspec(dllexport)
Hier nochmal die Deklaration der entsprechenden DLL-Methode in Delphi:
Delphi-Quellcode:
Ich würde mich tierisch freuen, wenn jemand hier einen Wink für mich hätte. Sonst muss ich mich nur weiterhin aufregen, dass der Entwickler dieser Pluginverwaltung unbedingt WideStrings nutzen muss, wo ich doch gelesen habe, dass man die grade in DLLs nicht unbedingt nehmen soll, sondern eher PChar, um eben solchen Problemen aus dem Weg zu gehen.
GetPlugInName = function : WideString; stdcall;
Vielen Dank an euch schonmal!!! Grüße, MacGyver2k |
Re: WideString aus C++ DLL-Methode an Delphi-Host zurückgebe
Ich denke du wirst hier mit StringToOleStr arbeiten müssen um einen COM-String zu bekommen der nicht mehr unter der Speicherverwaltung von Delphi steht.
|
Re: WideString aus C++ DLL-Methode an Delphi-Host zurückgebe
Eigentlich braucht er in C nur den COM- / OLE-String verwalten
und Delphi macht dieses automatisch, bei Verwendung des WideString ![]() ![]() ![]() ![]() Delphi kapselt diese Befehle im WideString und dort wird alles nur an die WinAPI der oleaut32.dll weitergereicht. Ich weiß jetzt nicht ob C dafür eventuell eine Klasse oder sowas hat, welches dieses auch schon kapselt, aber er braucht die Funktionen dann in C nur als LPWSTR bzw. BSTR deklarieren, deren Inhalt in C über die oben genannten Funktionen verwalten und in Delphi an gleicher Stelle der Funktionen alles einfach als WideString definieren. etwa so:
Code:
bool DECLDIR EXTP_IsPlugIn( BSTR name )
Delphi-Quellcode:
function EXTP_IsPlugIn(const name: WideString): LongBool; stdcall;
// oder function EXTP_IsPlugIn(var name: WideString): LongBool; stdcall; [add] war jetzt bool = ByteBool/Boolean und BOOL = LongBool ? :gruebel: wenn ja, dann natürlich anpassen. |
Re: WideString aus C++ DLL-Methode an Delphi-Host zurückgebe
Bei Strings ist doch const nicht gleich var, oder? :gruebel: Const sollte doch nur bewirken, dass keine Kopie angefertigt wird, und nicht die Übergabe beeinflussen.
Die WideString-Rückgabe dürfte übrigens nicht im EAX-Register erfolgen, sondern über einen versteckten Parameter, also ungefähr so:
Code:
void Foo(LPWSTR* result)
|
Re: WideString aus C++ DLL-Methode an Delphi-Host zurückgebe
Probier doch einfach das:
Delphi-Quellcode:
GetPlugInName : array [0..xxxx] of WChar;
|
Re: WideString aus C++ DLL-Methode an Delphi-Host zurückgebe
Zitat:
Von Seiten der Schnittstelle ist aber CONST und VAR genau gleich, nur daß bei CONST der Parameterinhalt nicht geändert wird (werden darf) und bei VAR darf sich der Inhalt ändern kann. @hathor: bezüglich der Speicherverwaltung könnte man da auch einfach auf PWideChar/LPWSTR umsteigen und Derjenige, welcher die Daten haben möchte übergibt dort einfach den nötigen Puffer (eventuell noch einen "BufferLen"-Parameter mit übergeben und auf der Füllenden Seite prüfen, ob der Puffer auch groß genug ist) |
Re: WideString aus C++ DLL-Methode an Delphi-Host zurückgebe
Zitat:
|
Re: WideString aus C++ DLL-Methode an Delphi-Host zurückgebe
für String/AnsiString/WideString/UnicodeString:
CONST, VAR und OUT ist alles call-by-reference Ohne Angabe (von CONST VAR OUT) ist es zwar ebenfalls call-by-reference, allerdings wird da der Inhalt kopiert bzw. der Referenzzähler erhöht. Bei einem WideString wird also ohne Angabe eine neue Kopie angelegt, wärend VAR und CONST nur die Referenz übernehmen. Ansonsten geben diese (VAR, CONST, OUT und nix) nur an, wie/ob der Parameterinhalt behandelt wird. |
Re: WideString aus C++ DLL-Methode an Delphi-Host zurückgebe
Das kann nicht sein, Himitsu. Ein var Widestring muss ein Zeiger auf einen PWideChar sein, sonst könntest du in der Routine nichts ändern. Const und fehlende Angabe resultieren hingegen in der Übergabe als PWideChar.
|
Re: WideString aus C++ DLL-Methode an Delphi-Host zurückgebe
ach menno, das Wetter ist wohl doch zu schlimm :|
OK, von der Übergabe ist es doch nicht gleich also CONST und NIX ist gleich (call-by-const-reference), sowie VAR und OUT (call-by-var-reference) :oops: aber was die Behandlung der Inhalte angeht, bleibt es unverändert :angel2: also dann so?
Delphi-Quellcode:
bool DECLDIR EXTP_IsPlugIn( BSTR name )
function EXTP_IsPlugIn(const name: WideString): Boolean; stdcall; bool DECLDIR EXTP_IsPlugIn( BSTR* name ) function EXTP_IsPlugIn(var name: WideString): Boolean; stdcall; |
Re: WideString aus C++ DLL-Methode an Delphi-Host zurückgebe
Hi Leute,
schon mal vielen Dank für die zahlreiche Teilnahme an meinem Problem. Ich muss jetzt erstmal alle Posts durchlesen und dann handeln! Aber wie das so im Überfliegen aussieht, ist bestimmt geiles dabei! Ich melde mich später wieder! Grüße MacGyver2k |
Re: WideString aus C++ DLL-Methode an Delphi-Host zurückgebe
So nun hab ich alles gelesen und habe auch einiges davon ausprobiert. Leider funktioniert es immernoch nicht.
Zunächst muss ich leider sagen, dass die meisten Vorschläge auf Änderungen am Delphi Code hinauslaufen. Ich habe leider nicht extra erwähnt, dass ich den Delphi Code zwar habe, ihn aber nicht abändern kann. Würde wohl auch mit bestehenden Plugins ins Gehege kommen. Es geht auch wirklich ausschließlich daraum, wie ich den String aus C/C++ an Delphi zurückgebe. Denn Stringparameter von Delphi nach C kommen ohne probleme an. Ich hab nun mal alles möglich eingebaut, was nur irgendwie sinnvoll scheint. Dabei haben mich die Hinweise von himitsu am meisten inspiriert. Außerdem habe ich auch wie Apollonius schrieb, mal das mit dem versteckten Parameter probiert. Es kommt wie gesagt immernoch nichts raus.
Code:
ich bin echt so langsam am verzweifeln :wall:
DECLDIR LPCWSTR EXTP_GetPlugInName( LPCWSTR result )
{ LPWSTR buffer = NULL; int size = MultiByteToWideChar( CP_ACP, 0, "MyPluginName", -1, NULL, 0 ); buffer = (WCHAR*) malloc( sizeof( WCHAR ) * size ); MultiByteToWideChar( CP_ACP, 0, "MyPluginName", -1, buffer, size ); result = SysAllocStringLen( buffer, size ); return result; //return PlugIn.GetPlugInName(); } |
Re: WideString aus C++ DLL-Methode an Delphi-Host zurückgebe
Ich sprach von einem Zeiger auf einen LPWSTR. :wink: Ohne die zusätzliche Inidrektion kann kein Wert zurück übertragen werden.
|
Re: WideString aus C++ DLL-Methode an Delphi-Host zurückgebe
hi Apollonius,
danke für den Wink. Ich hab nun so wie ich es mir am plausibelsten denken konnte, das mit dem Zeiger auf LPWSTR probiert. So wie ich es hier implementiert habe, funktioniert es leider nach wie vor nicht :( habe ich immernoch einen logik-fehler bei der ganzen Sache?
Code:
LPWSTR entspricht dabei ja WCHAR*
DECLDIR LPWSTR* EXTP_GetPlugInName( WCHAR** result )
{ int size = MultiByteToWideChar( CP_ACP, 0, "MyPluginName", -1, NULL, 0 ); result = new WCHAR*; *result = new WCHAR[size]; MultiByteToWideChar( CP_ACP, 0, "MyPluginName", -1, *result, size ); return result; } Ich hoffe, dass ich wirklich noch irgendwo einen Hänger in meinem Kopf habe, den mir vieleicht irgendjemand aufzeigen kann. Weiterhin Danke alle Helfer - auch im Voraus! |
Re: WideString aus C++ DLL-Methode an Delphi-Host zurückgebe
Dein Code aus #12 war schon fast richtig. Die Zuweisung in der vorletzten Zeile wird nur nicht an den Aufrufer durchgereicht, daher sollte das so aussehen:
Code:
Der Rückgabetyp der Funktion sollte void sein. Außerdem solltest du buffer wieder freigeben.
DECLDIR void /*!*/ EXTP_GetPlugInName( LPCWSTR* /*!*/ result )
{ LPWSTR buffer = NULL; int size = MultiByteToWideChar( CP_ACP, 0, "MyPluginName", -1, NULL, 0 ); buffer = (WCHAR*) malloc( sizeof( WCHAR ) * size ); MultiByteToWideChar( CP_ACP, 0, "MyPluginName", -1, buffer, size ); *result /*!*/ = SysAllocStringLen( buffer, size ); free(buffer); //! } |
Re: WideString aus C++ DLL-Methode an Delphi-Host zurückgebe
Hi Apollonius,
ich krieg nen Knall - es geht!!! Du hast mir damit wirklich extremst geholfen! :cheers: Das ganze öffnet mir nun den Weg, um über C++/CLI eine Bräsche zu .NET Code zu schlagen, und in meinen Plugins .NET Code einzusetzen. Nochmals vielen Dank an Apollonius und natürlich auch alle anderen die hier ihre Zeit geopfert haben! THX! |
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:42 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