DllCall auf eine unicode-DLL

Alle Fragen um die Programmierung, die sich sonst nicht kategorisieren lassen. Von Makro bis Codeblock, von IF bis ENDIF

Moderator: Moderatoren

Antworten
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14641
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 87 Mal
Kontaktdaten:

DllCall auf eine unicode-DLL

Beitrag von Jan »

Ich habe gerade das problem, das ich mit DllLoad() eine DLL lade, dann aber bei dem folgenden DllCall() scheitere mit der Meldung, das DllPrepareCall() die aufgerufene Funktion nicht finden kann.

Code: Alles auswählen

nDll := DllLoad("DieDll.dll")
IF nDll > 0
   dummy := dllCall(hdll, DLL_CDECL, "DerFunktionsAufruf", "DerErsteParameter", "DerNaechsteParameter")
OK, ich selber benutze ja garkein DllPrepareCall(), aber DllCall() macht das anscheinend intern.

Ich habe das Forum durchstöbert und bin auf den Hinweis gestoßen, das bei Unicode-DLL die Variablen anders behandelt werden müssen. Aber wie soll ich das machen?

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15689
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: DllCall auf eine unicode-DLL

Beitrag von brandelh »

zunächst prüfen ob es darin Funktionen für ANSI gibt ;-) bzw. eine ANSI Version von der dll.

Und dann nimm die ot4xb !

Wenn du dir meine HBPrintPDF ansiehst, wird dir auffallen wie man die genauen Parametertypen gegenüber der DLL angibt.
Es gibt dort auch einen für unicode strings. Mit Umwandlung von ANSI nach UNICODE und zurück, das macht die ot4xb automatisch wenn man den richtigen Typ angibt.
Ich nutze auch eine Funktion, die intern OEM nach ANSI umsetzt wenn das nötig ist, daher kann meine Klasse unabhängig von der set charset Einstellung immer richtig arbeiten ;-)
Gruß
Hubert
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14641
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 87 Mal
Kontaktdaten:

Re: DllCall auf eine unicode-DLL

Beitrag von Jan »

Hallo Hubert,

Danke für den Hinweis. Wenn ich jetzt auch nicht weiß, was ich machen soll. ot4xb ist ja kein Problem, die habe ich ohnehin im Einsatz. Aber wie soll ich die benutzen, welche Funktion dadrin?

Und nein, die DLL gibt es nicht als ANSI.

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15689
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: DllCall auf eine unicode-DLL

Beitrag von brandelh »

Hallo Jan,

lade dir meine Klasse runter und sieh dir die Syntax an !

dann reden wir weiter ;-)

Am besten baust du dir auch so eine Klasse, sie kann ja zunächst auf die nötigen Funktionen beschränkt sein.
Gegenüber von Xbase kann man so eine einheitliche einfache Syntax hinbiegen und nur intern die komplexeren Dinge behandeln.
Z.B. Zeichensatz, Default Texte, Formatumwandlungen, Rückgabe 0/1 => .f./.t. und und und ...
Beispiel für DrawText() hat geschrieben:int DPLAppendText(int InstanceID, wchar_t * Text);

Code: Alles auswählen

// -------------------------------------------------------------------------------------------------------------------
METHOD HBPrintPDF:DrawText(nXPos, nYPos, sText)
   sText := ::ForceAnsi(sText)
return FpQCall( {::_hdll_,"DPLDrawTextA"} ,"__sl__sl__f8__f8__pt",::_id_,nXPos, nYPos, sText)
wie man sieht, übernimmt die Klasse das Handling des DLL-Handle (hier InstanceID), in diesem Beipspiel liefert die Funktion einen numerischen Wert zurück, der aber hier nicht benötigt wird.
In anderen Fällen liefern Funktionen 0/1 zurück und ich setze um auf return 0 # FpQCall etc.

Falls der Anbieter seine DLL ändert (was dummerweise vorkommt) kann man viele Änderungen elegant in der Klasse abfangen, ohne jedesmal den Quellcode der anderen Programme anzupassen.
Gruß
Hubert
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15689
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: DllCall auf eine unicode-DLL

Beitrag von brandelh »

hier die Parameter Erklärung:

der 1. FormatStringParameter (hier __sl) ist der Typ den die Funktion zurückgeben soll, hier LONG.
Ein ANSI Parameter String wird als __pt angegeben, auch wenn der Text geändert werden kann.
Ein UNICODE String wird mit c_sw übergeben, wobei er auf Xbase++ Seite ein normaler ANSI String ist.

Code: Alles auswählen

#xtranslate AS STR2WIDE                => AS QTYPE "c_sw"
Falls du eine Funktion mit Rückgabewert auf einen String hast, wird es komplexer, da der Speicher welcher die DLL nutzt wieder freigegeben werden muss.
Es gibt auch noch den c@sw, da muss ich in meinen alten eMails nachsehen für was der ist ;-)

Code: Alles auswählen

#xtranslate AS STR2WIDE_W              => AS QTYPE "c@sw"
Gruß
Hubert
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15689
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: DllCall auf eine unicode-DLL

Beitrag von brandelh »

Das ist so eine Funktion, die einen Unicode String (besser den Pointer darauf) zurückliefert:
wchar_t * DPLDrawHTMLTextBox(int InstanceID, double Left, double Top,
double Width, double Height, wchar_t * HTMLText);
und DOUBLE Variablen werden auch benötigt: __f8

Code: Alles auswählen

// -------------------------------------------------------------------------------------------------------------------
METHOD HBPrintPDF:DrawHTMLTextBox(nLeft, nTop, nWidth, nHeight, sHTMLText)
   sHTMLText := ::ForceAnsi(sHTMLText)
return ::ReadString(::_str_result_(FpQCall( {::_hdll_,"DPLDrawHTMLTextBoxA"} ,"__pt__sl__f8__f8__f8__f8__pt",::_id_,nLeft, nTop, nWidth, nHeight, sHTMLText)))
In dieser Klasse richte ich mich bei der Parameterübergabe and die ActiveX Schnittstelle (also ohne 1. Parameter) und ::setze OEM auf ANSI um.
_str_result_() ist eine Funktion im Quellcode von Pablo, die den Text abholt und den Speicher freigibt.
Gruß
Hubert
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15689
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: DllCall auf eine unicode-DLL

Beitrag von brandelh »

Hier ist die richtige Anleitung ...

Code: Alles auswählen

Autoconvert Ansi to Unicode: 	c_sw  statt  __pt  >> nur wenn Parameter LPSTR oder LPCSTR nach LPWSTR oder LPCWSTR wurden.
Parameter per Reference mit :   c@sw

Rückgabewerte c_sw statt c_sz liefern einen Xbase++ Ansi String statt dem Pointer.
Der letzte Pointer kann mit qfpGetLastPointer() ermittelt werden um Speicher frei zu geben ...
Also ist ein Rückgabewert eines Strings c_sz statt __pt ... wenn man keinen Pointer möchte, aber ob dann der Speicher freigegeben wird ?
Gruß
Hubert
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15689
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: DllCall auf eine unicode-DLL

Beitrag von brandelh »

PS: du darfst natürlich meine Klasse als Vorlage nutzen inkl. Pablos Sonderfunktionen()
Gruß
Hubert
Antworten