XBase++ und DLLs

Zugriff, Engines, Konvertierung. Von ADS über DBF bis zu SQL.

Moderator: Moderatoren

Antworten
kuhno
UDF-Programmierer
UDF-Programmierer
Beiträge: 54
Registriert: Sa, 07. Jan 2006 17:30
Wohnort: Braunschweig
Kontaktdaten:

XBase++ und DLLs

Beitrag von kuhno »

Hallo zusammen,

ich habe da ein kleines Problem, bei dem ich moment nicht so richtig weiter komme. :? Ich möchte eine DLL einbinden, und zwar die libpq.dll um damit auf den PostgreSQL-Server zuzugreifen. Das ist mir inzwischen auch soweit gelungen, (die richtige DLL war schon ein Abenteuer) aber die Rückgabewerte diese DLL werden nur numerisch zurückgegeben. Die DLL selbst gibt aber Strings zurück. Irgendwie klappt das nicht so wie ich mir das vorstelle. Unter Clipper konnte man ja eine LIB stricken und diese dann mit dem Linker einbinden. Das scheint hier aber nicht zu gehen? Gibs da einen workaround für diese Problem oder bin ich da der Erste? Ich habe im Internet jedenfalls nichts darüber gesehen.

Gruß
Manfred
Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
Beiträge: 16502
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin
Hat sich bedankt: 111 Mal
Danksagung erhalten: 48 Mal
Kontaktdaten:

Beitrag von Martin Altmann »

Guten Morgen Manfred,
sorry, schon wieder nur ich :) - habe aber lange genug gewartet :wink:
Wahrscheinlich liegt das Problem darin begründet, dass der Funktionsaufruf aus der DLL nicht einen Pointer, sondern einen Pointer auf einen Pointer zurückgibt (ich liebe C :roll: )
Schau Dir mal dieses Add-on auf der Seite von Phil Ide an - vielleicht hilft Dir das bei Deinem Problem weiter?

Viele Grüße,
Martin
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9345
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 100 Mal
Danksagung erhalten: 359 Mal
Kontaktdaten:

Beitrag von Tom »

Hallo, Manfred.

Wenn man eine Fremd-DLL einbinden will, gibt es nur dann LIBs, wenn es sich um Xbase-Code handelt, ansonsten greift man auf DLLs via DLLLoad() zu, oder etwas einfacher mit Hilfe von DLLFUNCTION. Dieser Aufruf hier beispielsweise bindet die Funktion TapiRequestMakeCall() aus der DLL TAPI32.DLL ein. Auf diese Art kann man die Windows-Wählhilfe nutzen:

Code: Alles auswählen

DLLFUNCTION TapiRequestMakeCall (cNumber,cCaption,cText,cBuffer) ;
         USING STDCALL FROM TAPI32.DLL
Der Aufruf erfolgt dann irgendwo im Programm auf z.B. diese Art:

Code: Alles auswählen

TapiRequestMakeCall (cNumber,"Mein Programm",cName,"")
Wie Du im ersten Beispiel sehen kannst, genügt diese DLL Windows-Standardkonventionen (USING STDCALL), aber es gibt auch DLLs, die nach C-Konventionen eingebunden werden müssen (USING CDECL). Es ist wichtig, zu wissen, ob Parameter per Referenz oder per Wert übergeben werden. Viele DLLs "besetzen" Parameter mit Rückgabewerten, so daß der Aufruf so erfolgt:

Code: Alles auswählen

cBuffer := space(255)
nRetValue := _My_DLL_Function(par1, par2, @cBuffer)
nRetValue gibt ausschließlich Auskunft darüber, ob die Funktion ausgeführt werden konnte, aber in cBuffer steht ihr eigentlicher Rückgabewert. Um mehr darüber zu sagen, wie das in Deinem Fall aussehen muß, müßte man die DLL und ihre Beschreibung kennen.
Herzlich,
Tom
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9345
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 100 Mal
Danksagung erhalten: 359 Mal
Kontaktdaten:

Beitrag von Tom »

Ergänzung:
um damit auf den PostgreSQL-Server zuzugreifen
Das geht natürlich auch mit Hilfe der ODBCDBE von Alaska oder - etwas eleganter - mit Hilfe von SQLexpressvon Boris Borzic.
Herzlich,
Tom
kuhno
UDF-Programmierer
UDF-Programmierer
Beiträge: 54
Registriert: Sa, 07. Jan 2006 17:30
Wohnort: Braunschweig
Kontaktdaten:

Schnittstellen

Beitrag von kuhno »

Hallo Martin,

vielen Dank für den Link. Das sieht sehr gut aus. Ich werde das mal ausprobieren. :idea:

Gruß
Manfred
kuhno
UDF-Programmierer
UDF-Programmierer
Beiträge: 54
Registriert: Sa, 07. Jan 2006 17:30
Wohnort: Braunschweig
Kontaktdaten:

XBase++ und DLLs

Beitrag von kuhno »

Hallo Tom

Danke für den Hinweis. Den letzten Code-Block werde ich mal ausprobieren.

Code: Alles auswählen

cBuffer := space(255)
nRetValue := _My_DLL_Function(par1, par2, @cBuffer)
^
Diese obige Stelle wird wohl die Lösung bringen.

Gruß
Manfred
kuhno
UDF-Programmierer
UDF-Programmierer
Beiträge: 54
Registriert: Sa, 07. Jan 2006 17:30
Wohnort: Braunschweig
Kontaktdaten:

Beitrag von kuhno »

Hallo Tom

das ^-Zeichen sollte unter dem @-Zeichen stehen und quote am Schluß kam irgendwie automatisch.

Gruß
Manfred
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9345
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 100 Mal
Danksagung erhalten: 359 Mal
Kontaktdaten:

Beitrag von Tom »

Wenn Du auf den EDIT-Button rechts über Deiner Nachricht klickst, kannst Du sie bearbeiten und solche Fehlerchen korrigieren. :sign6:
Herzlich,
Tom
kuhno
UDF-Programmierer
UDF-Programmierer
Beiträge: 54
Registriert: Sa, 07. Jan 2006 17:30
Wohnort: Braunschweig
Kontaktdaten:

Beitrag von kuhno »

Hallo Tom

Danke für den Hinweis :wink: , aber rechts über meiner Nachricht steht als letztes URL und sonst weiter nix. Ich arbeite mit dem Mozilla und das ouote-Zeichen ist beim klick auf Absenden automatisch erschienen :cry: . Da war auch schon nix mehr Edit :( .

Gruß
Manfred
Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
Beiträge: 16502
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin
Hat sich bedankt: 111 Mal
Danksagung erhalten: 48 Mal
Kontaktdaten:

Beitrag von Martin Altmann »

Hallo Manfred,
Tom meinte, dass Du in der normalen Threadübersicht oben rechts auf edit klicken kannst (der zweite Knopf), um Dein entsprechendes posting nachträglich zu editieren.
Was Du meinst, sind die Knöpfe in der Editieransicht.
Wenn Du einen Beitrag absendest, werden automatisch alle noch nicht geschlossenen "tags" beendet - wahrscheinlich hast Du etwas zitieren wollen und auf den Quote-Knopf geklickt, ohne vorher was markiert zu haben. Den dann eingefügten Tag wirst Du wieder manuell gelöscht haben. Das System hat sich aber gemerkt, dass der Tag noch geschlossen werden muss (die Bezeichnung des Knopfes erhält dann auch ein * hinter dem Quote). Wenn Du dann nochmals auf den Knopf klickst, wird der tag ordentlich beendet (funktioniert genauso auch mit den anderen Knöpfen - entweder vorher den Text markieren und dann auf den entsprechenden Knopf klicken, oder aber auf den entsprechenden Knopf klicken, den Text schreiben und den Knopf erneut anklicken).
Da Du dies wahrscheinlich nicht gemacht hast, hat beim Absenden Deines Postings das System den schließenden quote-tag automatisch eingefügt.

Viele Grüße,
Martin
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9345
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 100 Mal
Danksagung erhalten: 359 Mal
Kontaktdaten:

Beitrag von Tom »

Hallo, Manfred.

Lies Dir mal die "FAQ" zum Thema "Nachrichten schreiben und editieren" durch:

http://www.xbaseforum.de/faq.php
Herzlich,
Tom
kuhno
UDF-Programmierer
UDF-Programmierer
Beiträge: 54
Registriert: Sa, 07. Jan 2006 17:30
Wohnort: Braunschweig
Kontaktdaten:

Xbase++ und DLL

Beitrag von kuhno »

Hallo zusammen,

nun ist viel Zeit seit dem letzt Mal vergangen. Die DLL libpq.dll läßt sich problemlos einbinden. Die Aufrufe mit DllPrepareCall und DllExecuteCall scheinen zu funktionieren. Was noch Probleme macht ist die Antwort der Funktionen. Eine Dereferenzierung liefert m.E. nur Blödsinn. Wenn ich mich mit dem PostgeSQL-Server über Netz verbinde, dann kann ich mit Ethereal auf den Linuxserver sehen, das Daten ausgetauscht werden. Die sehen auch gut aus. Wenn ich dann über PQstatus abfrage, ob die Verbindung OK ist, dann sollte eigentlich der String CONNECTION_OK kommen. Nach Deref kommt aber nur das ASCII-Zeichen 1 an.
Wenn ich aber PQhost abfrage, dann kommt über die Deref ein wilder String an. Ich habe mal das mir mit einem Hex-Editor angesehen. Der Anfang sieht so aus: D0 92 0E 42 AE 92 0E 42 8C 92 0E 42 50 93 0E

Was mir dabei auffällt ist, das immer eine Sequenz mit 42 eingeleitet wird und mit 92oder 93 0E beendet wird. (Alles in Hex). Ein Block wird dazwischen aber statt mit 92 mit 34 0F beendet.

Das sieht so aus, als würde hier eine Blockweise Übertragung mit was weiss ich vonstatten gehen.

Wer hat da mal ein Auge drauf und kann mir auf die Sprünge helfen?

Gruß

Manfred Kuhn
Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
Beiträge: 16502
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin
Hat sich bedankt: 111 Mal
Danksagung erhalten: 48 Mal
Kontaktdaten:

Beitrag von Martin Altmann »

Hallo Manfred,
ich mache zwar nicht viel mit DLLs, aber damit die anderen Dir besser helfen können, wäre natürlich Code Deinerseits sehr hilfreich!
Zeige doch mal bitte, wie Du die DLL aufrufst - mit allem, was dazu gehört (also initialisieren der Parameter, vorbereiten, ...) und wenn möglich auch, wie die Ergebniss des Aufrufes aussehen sollten!

Viele Grüße,
Martin
:grommit:
Webseite mit XB2.NET und ausschließlich statischem Content in Form von HTML-Dateien: https://www.altem.de/
Webseite mit XB2.NET und ausschließlich dynamischem Content in Form von in-memory-HTML: https://meldungen.altem.de/

Mitglied der XUG Osnabrück
Vorsitzender des Deutschsprachige Xbase-Entwickler e. V.
kuhno
UDF-Programmierer
UDF-Programmierer
Beiträge: 54
Registriert: Sa, 07. Jan 2006 17:30
Wohnort: Braunschweig
Kontaktdaten:

Beitrag von kuhno »

Hallo Martin,

danke für die schnelle Reaktion.

Nochmal zum Problem. Hier der Code zum öffen der Dll. Wenn ich falsche DLL einbinde kommt auch eine Fehlermeldeung.
Code:

Code: Alles auswählen

nDllHandle:=DllLoad("libpq.dll")

IF nDllHandle=0
   ??"DLL konnte nicht geladen werde. DOS-Fehler:"
   ? DosErrorMessage(DosError())
   Inkey(0)
   quit
endif
In der Funktion wird dann die Datenbank geöffnet:

Code: Alles auswählen

cTemplate:=DllPrepareCall(nDllHandle,DLL_CDECL,"PQconnectdb")
status:=DllExecuteCall(cTemplate,"hostaddr=192.168.1.101 dbname=versuch user=postgres password=test1")

*** status enthält Handle auf geöffnete und verbundene DB
cStringa:=PGDeref(status)
Hier wird vermutlich nix vernünfiges als String zurückkommen. Nun möchte ich den Status abfragen. Ich mache das so:

Code: Alles auswählen

cString3:="Hallo, was ist das?                                       "
status3:=DllCall( nDllHandle,DLL_CDECL,"PQstatus")
cString3 := PGDeref(status3)
Wenn ich statt "PQstatus" die 14 einsetze, dann ist das Ergebnis gleich. Der dereferenzierte String cString3 ist dann 1( ASCII-Wert 1). Es sollte "Connection_OK" zurückkommen.

Anders Beispiel:

Code: Alles auswählen

status_x:=""
conn4:=DllPrepareCall(nDllHandle,DLL_CDECL,10)
status4:=DllExecuteCall(conn4,status_x)
cString4 := PGDeref(status4)
Hier will ich den Host zurückbekommen. 10 steht für "PQhost". Nach der Dereferenzierung sieht der String so aus:

Code: Alles auswählen

Ð’B®’BŒ’BP“B.“B“Bk’BN4B1’B ’B5”BZ/BÂB¶B ÖB ÖB ÖB ÖB ÖB ÖB
Das ist ein bisschen merkwürdig.
Hier nochmal in HEX-Darstellung:

Code: Alles auswählen

   
OFFEN.txt: 1/1 
00000000  d0 92 0e 42 ae 92 0e 42 8c 92 0e 42 50 93 0e 42  ...B...B...BP..B
00000010  2e 93 0e 42 11 93 0e 42 6b 92 0e 42 4e 34 0f 42  ...B...Bk..BN4.B
00000020  31 92 0e 42 20 92 0e 42 35 94 0e 42 5a 2f 0f 42  1..B ..B5..BZ/.B
00000030  c2 19 0f 42 b6 19 0f 42 20 d6 1e 42 20 d6 1e 42  ...B...B ..B ..B
00000040  20 d6 1e 42 20 d6 1e 42 20 d6 1e 42 20 d6 1e 42   ..B ..B ..B ..B
Hex-Dump erzeugt von GHex 2.2.1
 
Ich hoffe, das ist jetzt ein bisschen ausführlicher geworden.

Gruß

Manfred Kuhn
kuhno
UDF-Programmierer
UDF-Programmierer
Beiträge: 54
Registriert: Sa, 07. Jan 2006 17:30
Wohnort: Braunschweig
Kontaktdaten:

Beitrag von kuhno »

Eins hab ich noch vergessen:

Es ist egal, ob ich DllCall oder die Kombination von DllPrepareCall und DllExecuteCall benutze. Das Ergebnis ist gleich ( ASCII 1).

Gruß
Manfred Kuhn
Antworten