DllCall() und numerische Rückgabewerte [erledigt]

Fragen rund um diverse Windows-Versionen, ihr Verhalten unter Xbase++ und den Umgang mit der API

Moderator: Moderatoren

Antworten
Benutzeravatar
Werner_Bayern
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2120
Registriert: Sa, 30. Jan 2010 22:58
Wohnort: Niederbayern
Hat sich bedankt: 29 Mal
Danksagung erhalten: 70 Mal

DllCall() und numerische Rückgabewerte [erledigt]

Beitrag von Werner_Bayern »

Servus,

was mache ich hier falsch?

Code: Alles auswählen

function C-Lib_ReadNum(nRow, nCol, nWert)
local nRueck
//nRueck := dllcall("c-lib.dll", DLL_CDECL, "ReadNumA", nRow, nCol, nWert)
nRueck := double2long(nFpCall({"c-lib.dll", "ReadNumA"}, nRow, nCol, nWert))
return nRueck
Lt. der Doku der Lib ist der Rückgabewert double (kein Pointer). Aber weder mit double2long noch ohne (was eigentlich ja auch korrekt sein müsste, da Xbase++ ja konvertiert?) bekomme ich richtige Werte zurück. Anstatt einer 3 z. B. 1074266112.
Ausserdem stürzt Xbase ab, wenn die Funktion 3x hintereinander aufgerufen wird mit "interne Datenstrukturen beschädigt". Oder nRueck in o. g. Function ist z. B. lt. VX plötzlich ein anderer als er bisher war (gleiche Parameter für nRow und nCol), im aufrufenden Teil des Programmes hat dann der Rückgabewert wird die o. g. Zahl! Mache ich es step by step im VX, wird der Wert richtig zurück gegeben (aber halt der falsche Wert) und es kommt auch kein Absturz!. Ein sleep oder wait bringen NICHTS. :?:

Habs auch schon als Pointer mit den versch. Peek-Versionen getestet, immer "interne Datenstrukturen beschädigt"...
Zuletzt geändert von Werner_Bayern am Sa, 08. Dez 2012 15:49, insgesamt 1-mal geändert.
es grüßt

Werner

<when the music is over, turn off the lights!>
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12903
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 44 Mal

Re: DllCall() und numerische Rückgabewerte

Beitrag von AUGE_OHR »

hi,

Frage : reden wir hier von einer "fertigen" DLL oder stellst du die "C"-DLL selbst her ?

wenn du eine eigene "C"-DLL erstellen willst siehe dir c:\ALASKA\XPPW32\Source\samples\basics\CAPI\soundex.c an

was mir auffällt : Parameter ohne "Reference" ?

Code: Alles auswählen

DllCall(hDll,DLL_CDECL,"My_C_Func",0,@hBuffer)
ich kenne das so das man, aus Xbase++, die Variable / Type "vorbelegt" und per "Reference" übergibt.
gruss by OHR
Jimmy
Benutzeravatar
Werner_Bayern
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2120
Registriert: Sa, 30. Jan 2010 22:58
Wohnort: Niederbayern
Hat sich bedankt: 29 Mal
Danksagung erhalten: 70 Mal

Re: DllCall() und numerische Rückgabewerte

Beitrag von Werner_Bayern »

Wir reden von einer "fertigen" DLL, auf die ich keinen Einfluss habe.
Nein, die Parameter müssen nicht per Referenz übergeben werden, weil die C-Funktion nur einen Rückgabewert liefert. Ansonsten müssen sie ja als Pointer übergeben werden, was in Xbase++ soviel wie per Referenz heißt?

Ich hab das Problem übrigens nur bei Rückgabewerten double bisher bei dieser Lib. Pointer auf Charakter-Rückgabewerte funktionieren einwandfrei mittels

Code: Alles auswählen

local nPointer := dllcall(...)
return if(empty(nPointer), "", Peekstr(nPointer, 0, -1))
es grüßt

Werner

<when the music is over, turn off the lights!>
georg
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2823
Registriert: Fr, 08. Feb 2008 21:29
Hat sich bedankt: 95 Mal
Danksagung erhalten: 13 Mal

Re: DllCall() und numerische Rückgabewerte

Beitrag von georg »

Hallo, Werner -


gib doch OT4XB mal eine Chance. Ich habe mit Pablo's Bibliothek sehr gute Erfahrungen gemacht, was API Aufrufe angeht.
Liebe Grüsse aus der Eifel,

Georg S. Lorrig
Redakteur der Wiki des Deutschprachigen Xbase-Entwickler e.V.
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15688
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: DllCall() und numerische Rückgabewerte

Beitrag von brandelh »

Xbase++ DLLCALL() KANN KEINE DOUBLE Werte als Rückgabewert verarbeiten :!:
Ich vermute, dass das Zwischenergebnis irgendwie in eine Xbase numerisch gequetscht wird, aber tatsächlich noch Reste auf dem Stack übrig bleiben.
Sowas führt zu internal Errors !

Die QuickPDF gibt auch DOUBLE Werte zurück (in der PowerBasic INC kann man suchen nach ') as DOUBLE' ...
Ich nutze dafür die ot4xb Funktion FpQCall() die steht auch nicht so direkt in der doku ;-)
Dieser Funktion kannst du genau die Parametertypen inkl. Typ des Rückgabewertes mitteilen:

Code: Alles auswählen

METHOD HBPrintPDF:DAGetImageDblProperty(p1,p2,p3,p4)
return FpQCall( {::_hdll_,"DPLDAGetImageDblProperty"} ,"__f8__sl__sl__sl__sl__sl",::_id_,p1,p2,p3,p4)
                                                         ^_ Datentyp des Rückgabewertes der DLL, Rest Parameter
__f8 = FLOAT mit 8 Byte => DOUBLE
__sl = signed Integer => LONG

deine Funktion müsste also so aussehen:

Code: Alles auswählen

FpQCall( {"c-lib.dll", "ReadNumA"} ,"__f8__sl__sl__sl", nRow, nCol, nWert)
der Rückgabewert __f8 wird übrigens dann automatisch passend gemacht.
PS: DOUBLE entspricht "Double-precision floating-point numbers " ist also keine Integer Variable !
Zuletzt geändert von brandelh am Di, 13. Nov 2012 10:54, insgesamt 1-mal geändert.
Grund: Aussage oben korrigiert ;-)
Gruß
Hubert
Benutzeravatar
Werner_Bayern
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2120
Registriert: Sa, 30. Jan 2010 22:58
Wohnort: Niederbayern
Hat sich bedankt: 29 Mal
Danksagung erhalten: 70 Mal

Re: DllCall() und numerische Rückgabewerte

Beitrag von Werner_Bayern »

georg hat geschrieben:Hallo, Werner -

gib doch OT4XB mal eine Chance. Ich habe mit Pablo's Bibliothek sehr gute Erfahrungen gemacht, was API Aufrufe angeht.
Mach ich doch, verwende ich doch, siehe obiges Beispiel. Peekstr und nfpCall()
es grüßt

Werner

<when the music is over, turn off the lights!>
Benutzeravatar
Werner_Bayern
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2120
Registriert: Sa, 30. Jan 2010 22:58
Wohnort: Niederbayern
Hat sich bedankt: 29 Mal
Danksagung erhalten: 70 Mal

Re: DllCall() und numerische Rückgabewerte

Beitrag von Werner_Bayern »

Hubert,

=D>

Code: Alles auswählen

DLL c-lib.dll IMPORT C-Lib_ReadNum AS DOUBLE;
   PARAM nRow AS int,;
   PARAM nCOL AS int,;
   PARAM nWert AS int;
SYMBOL ReadNumA
Danke!

Wie war das nochmal:
Ich freue mich natürlich über jede Aufmerksamkeit und seien es auch nur nette Worte.
Was darf ich Dir Gutes tun? Eine Fl. Bio-Rotwein?
es grüßt

Werner

<when the music is over, turn off the lights!>
Benutzeravatar
Werner_Bayern
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2120
Registriert: Sa, 30. Jan 2010 22:58
Wohnort: Niederbayern
Hat sich bedankt: 29 Mal
Danksagung erhalten: 70 Mal

Re: DllCall() und numerische Rückgabewerte

Beitrag von Werner_Bayern »

brandelh hat geschrieben:Xbase++ KANN KEINE DOUBLE Werte als Rückgabewert verarbeiten :!:
Dann habe ich das falsch verstanden von Pablo:
Xbase++ internally store numeric values in one of these formats 32 bit signed integer (LONG) and 64 bit floating point (double). Xbase++ will store values with a decimal component always as a double and will try to store integer values as a LONG if possible, and if the value not fit inside a LONG will store it also as a double.
es grüßt

Werner

<when the music is over, turn off the lights!>
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15688
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: DllCall() und numerische Rückgabewerte

Beitrag von brandelh »

Werner_Bayern hat geschrieben:
brandelh hat geschrieben:Xbase++ KANN KEINE DOUBLE Werte als Rückgabewert verarbeiten :!:
Dann habe ich das falsch verstanden von Pablo:
Xbase++ internally store numeric values in one of these formats 32 bit signed integer (LONG) and 64 bit floating point (double). Xbase++ will store values with a decimal component always as a double and will try to store integer values as a LONG if possible, and if the value not fit inside a LONG will store it also as a double.
Sorry, ich war intern noch bei 64 bit unsigned Integers ... richtig ist, dass DLLCALL() ausschließlich LONG Rückgabewerte verarbeiten kann.
Die DLL Syntax hat was, aber ich persönlich brauche in den Funktionen mehr Freiheiten ;-)
Werner hat geschrieben: Wie war das nochmal:
Ich freue mich natürlich über jede Aufmerksamkeit und seien es auch nur nette Worte.
wo habe ich denn das schon wieder geschrieben ;-)

Ne lass den Wein mal wo er ist :D
Gruß
Hubert
Benutzeravatar
Werner_Bayern
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2120
Registriert: Sa, 30. Jan 2010 22:58
Wohnort: Niederbayern
Hat sich bedankt: 29 Mal
Danksagung erhalten: 70 Mal

Re: DllCall() und numerische Rückgabewerte

Beitrag von Werner_Bayern »

brandelh hat geschrieben:wo habe ich denn das schon wieder geschrieben ;-)
Ne lass den Wein mal wo er ist :D
Ach, kennst Du sicher auch, hbprint.prg, ist ein ganz gutes Teil ;-)

Dann nochmals Danke!
es grüßt

Werner

<when the music is over, turn off the lights!>
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:

Re: DllCall() und numerische Rückgabewerte

Beitrag von Tom »

Klar kann Xbase++ mit Doubles usw. umgehen. Die Wrapper konvertieren nur eben u.a. nach "numeric"*. Ich nehme an, dass der unerwartete Rückgabewert eigentlich einen Fehlercode markiert, denn eine DLL, die keinen per Referenz übergebenen Parameter besetzt (was eigentlich der Normalfall ist - und auch leichter zu behandeln), muss als Rückgabe die erwarteten Werte und Fehlercodes mischen. Wahrscheinlich schmiert es auch deshalb nach dem dritten Versuch ab - weil Fehler kaskadieren.

*aus der Doku: Bei allen anderen Aufrufkonventionen (Anm.: also bei nicht Xbase++-DLLs) ist der Rückgabewert vom Datentyp "numerisch".
Herzlich,
Tom
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15688
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: DllCall() und numerische Rückgabewerte

Beitrag von brandelh »

Hallo Tom,

als Parameter JA, als Rückgabewert NEIN !

Laut Auskunft vom Alaska Support vom 29.04.2010 ist es "gegenwärtig nicht möglich mit DLLCALL() Funktionen zu rufen, die als Rückgabe Typ ein double liefern".
Ich hatte das möglicherweise oben falsch geschrieben, ich weiß auch nicht mehr - ist schon etwas her - ob nach DLLCALL() das Programm dann abbricht,
oder ob der Wert nur auf LONG getrimmt wird. Wenn man aber eine genau Zahl braucht (0.00232322) ist die LONG Darstellung (0) auf jeden Fall unbrauchbar ;-)

Ansonsten gilt, dass die Funktion von ot4xb einfach den genauen Typ definieren kann und man somit mehr Möglichkeiten hat als sich auf die automatische Konvertierung zu verlassen.
Tom hat geschrieben:*aus der Doku: Bei allen anderen Aufrufkonventionen (Anm.: also bei nicht Xbase++-DLLs) ist der Rückgabewert vom Datentyp "numerisch".
da Xbase++ selbst keine TYP Deklaration vorsieht, ist die Aussage nicht sehr aussagekräftig (daher auch meine Anfrage damals an den Support) ;-)
Gruß
Hubert
Benutzeravatar
Werner_Bayern
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2120
Registriert: Sa, 30. Jan 2010 22:58
Wohnort: Niederbayern
Hat sich bedankt: 29 Mal
Danksagung erhalten: 70 Mal

Re: DllCall() und numerische Rückgabewerte

Beitrag von Werner_Bayern »

Tom hat geschrieben:Ich nehme an, dass der unerwartete Rückgabewert eigentlich einen Fehlercode markiert, denn eine DLL, die keinen per Referenz übergebenen Parameter besetzt (was eigentlich der Normalfall ist - und auch leichter zu behandeln), muss als Rückgabe die erwarteten Werte und Fehlercodes mischen. Wahrscheinlich schmiert es auch deshalb nach dem dritten Versuch ab - weil Fehler kaskadieren.
Servus Tom,

definitiv: Nein. Nach Umstellung auf o. g. Konvention läuft das Programm jetzt durch, ohne dass der Quelltext der aufrufenden Routinen umgestellt wurde. Der Rückgabewert bei nicht erfolgreichem Aufruf ist dann einfach 0.
Der genaue Fehlercode der C-Lib wird über eine eigene Funktion ermittelt.
es grüßt

Werner

<when the music is over, turn off the lights!>
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15688
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: DllCall() und numerische Rückgabewerte

Beitrag von brandelh »

Hi,

hier eine Anmerkung von Pablo zu dem Thema:
Pablo hat geschrieben:DllCall() return the content of EAX register but functions returning double store the result into the floating point stack so the value on EAX is anything else ( probably the result of any other internal call).
ndFpCall() (or FpQCall() with the template "__f8") calling the asm instruction FSTP to pop the value on the top of floating point stack and put into the Xbase++ return value, otherwise not only we got wrong values but also making the floating point stack grow forever.
Regards,
Pablo
ich denke dass ich es nicht übersetzen muss. Wenn man übrigens die obige DLL IMPORT Syntax in der PPO Datei ansieht,
sollten die commandos durch diese Funktionen (also entweder ndFpCall() oder FpQCall()) ersetzt worden sein.
Gruß
Hubert
Benutzeravatar
Werner_Bayern
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2120
Registriert: Sa, 30. Jan 2010 22:58
Wohnort: Niederbayern
Hat sich bedankt: 29 Mal
Danksagung erhalten: 70 Mal

Re: DllCall() und numerische Rückgabewerte

Beitrag von Werner_Bayern »

Servus Hubert,

danke. Nein, brauchst es nicht zu übersetzen. Ja, den Syntax hab ich mir auch schon in der ppo-Datei angesehen und deshalb auch entschieden, dass ich es so mache, weil ich diese kryptischen Strings für mich als nicht aussagekräftig empfinde.
es grüßt

Werner

<when the music is over, turn off the lights!>
Antworten