Eine Nichtypische Windows-Dll-Funktion aufrufen mit Python?

Python in C/C++ embedden, C-Module, ctypes, Cython, SWIG, SIP etc sind hier richtig.
jerch
User
Beiträge: 1630
Registriert: Mittwoch 4. März 2009, 14:19

Donnerstag 18. November 2010, 00:10

@funkheld:
Offensichtlich hast Du meinen letzten Post zu den Aufrufkonventionen ignoriert, ansonsten wäre Dir der Unterschied zwischen ProcedureDLL und -CDLL klar. Übertragen auf dein jetziges Problem heisst das, dass Freebasic unter Windows nur stdcall unterstützt. Damit werden auch die Symbole mit dem Funktionsname@Nummer in der DLL erklärbar.

PS: Ich kenne Freebasic nicht, allerdings scheint es auch cdecl zu verstehen. Siehe http://www.lowlevel.eu/wiki/FreeBASIC, zweites Beispiel.
BlackJack

Donnerstag 18. November 2010, 00:21

@jerch: Die verschiedenen Aufrufkonventionen, die FreeBASIC unterstützt, werden in dessen Dokumentation (kann man als CHM-Datei von der Homepage herunterladen) ausführlich erklärt. Was sie technisch gesehen bedeuten und wo sie eingesetzt werden -- sowohl Sprachen als auch Betriebssysteme. Und ziemlich am Anfang von der `ctypes`-Dokumentation steht auch etwas dazu -- sogar mit den gleichen Begriffen für die beiden Konventionen, die beide Seiten beherrschen. (FreeBASIC kennt noch eine dritte Variante, ``pascal``, die neben dem Namensgeber auch vom Vorbild QBasic und von Windows 3.x verwendet wird.)
funkheld
User
Beiträge: 224
Registriert: Sonntag 31. Oktober 2010, 09:26

Donnerstag 18. November 2010, 10:22

Hmmm...., ist schon ein graus. :D
Du hast recht, Freebasic macht anderen Mist.

Hab jetzt mal "XBLITE" , ist Freeware ausprobiert,... :D , macht eigentlich gute Sachen.

Davon laufen die DLL, bis auf die Floatrückgabe bzw Floatausgabe von Python.

Die Ausgabe von "d" ist "nan", also 3 Zeichen. Wie kommt die Floatausgabe hier?

Code: Alles auswählen

from sys import *
import ctypes

f = ctypes.windll.LoadLibrary("pydll.dll")
f.multf.restype = ctypes.c_float

c=10.788
d=f.multf(ctypes.c_float(c))
print d  >>>>>>>>>>> ausgabe ist "nan" als Buchstaben ???
XBLite:

Code: Alles auswählen

PROGRAM	"pydll"

EXPORT
DECLARE FUNCTION  multf ( SINGLE varf)
END EXPORT

FUNCTION  multf (SINGLE varf)
  SINGLE wertf
  wertf=11.5*varf	
  RETURN wertf
END FUNCTION

END PROGRAM

BlackJack

Donnerstag 18. November 2010, 10:43

@funkheld: FreeBASIC mach keinen "anderen Mist", sondern lässt Dir die Wahl. Du musst sie nur treffen und auf beiden Seiten -- FreeBASIC und `cpython` -- das jeweils passende wählen.

"Not a number" ("nan") ist der Wert für Ergebnisse die keine Zahl sind. Du verwendest wahrscheinlich in BASIC den falschen Datentyp. ``SINGLE`` klingt nach 4-Byte Fliesskommazahlen, `float` ist in Python aber 8 Bytes gross.

Edit: Sehe gerade dass Du ja `c_float` verwendet hast, daran kann es dann also nicht liegen. Dann weiss ich's auch nicht.
funkheld
User
Beiträge: 224
Registriert: Sonntag 31. Oktober 2010, 09:26

Donnerstag 18. November 2010, 17:28

Ja, sonst funktioniert es wunderbar in XBLite mit der DLL.
Ich brauch mich hier auch nicht mehr um ASM-Code zu kümmern.
Der XBLite schlägt alle Recorde.
Um einen bestimmten Bildpunkt auszuwerten aus einem 100kbBild, braucht er für das Arry, welches ich von Python übergebe 0.05 sec.
Eine Forschleife 10000000 mit 10000000x einen Wert an eine Variable zu übergeben braucht er 0.5 sec. So etwas brauche ich unter anderem bei dem Pythoninterpreter.
Der hat andere Stärken.

Gruss
jerch
User
Beiträge: 1630
Registriert: Mittwoch 4. März 2009, 14:19

Donnerstag 18. November 2010, 17:40

FYI: Es funktionieren beide Aufrufkonventionen mit FreeBASIC und Python ctypes, sowohl cdecl als auch stdcall.

cdecl:

Code: Alles auswählen

FUNCTION multf CDECL ALIAS "multf" (c AS SINGLE) AS SINGLE EXPORT
    RETURN c*5
END FUNCTION

Code: Alles auswählen

>>> import ctypes
>>> p=ctypes.cdll.LoadLibrary('bla.dll')
>>> p.multf
<_FuncPtr object at 0x00A2EB70>
>>> multf=p.multf
>>> multf.restype=ctypes.c_float
>>> multf(ctypes.c_float(5.1))
25.5
stdcall:

Code: Alles auswählen

FUNCTION multf STDCALL ALIAS "multf" (c AS SINGLE) AS SINGLE EXPORT
    RETURN c*5
END FUNCTION

Code: Alles auswählen

>>> import ctypes
>>> p=ctypes.windll.LoadLibrary('bla.dll')
>>> multf = getattr(p, 'multf@4')
>>> multf.restype = ctypes.c_float
>>> multf(ctypes.c_float(5.1))
25.5
funkheld
User
Beiträge: 224
Registriert: Sonntag 31. Oktober 2010, 09:26

Donnerstag 18. November 2010, 19:01

Na, siehste, dann ist das Freebasic doch nicht so gemein... :D

Im Forum konnte bis jetzt noch keiner sagen wie die Reihenfolge ist beim Aufruf.

Danke.

Gruss
funkheld
User
Beiträge: 224
Registriert: Sonntag 31. Oktober 2010, 09:26

Donnerstag 18. November 2010, 19:03

Wie funktionieren da die Zeigerübergabe an die DLL, wo dann evtl Daten übergeben werden in der DLL.

Gruss
jerch
User
Beiträge: 1630
Registriert: Mittwoch 4. März 2009, 14:19

Donnerstag 18. November 2010, 22:43

funkheld hat geschrieben:Wie funktionieren da die Zeigerübergabe an die DLL, wo dann evtl Daten übergeben werden in der DLL.
Verstehe leider den zweiten Teil der Frage nicht. Die Zeiger-Übergabe machst Du in Python z.B. mit ctypes.byref(). Gönn' Dir doch mal die 10min zum Durchlesen der ctypes-Einführung, da steht das alles mit Bsp. erklärt.
funkheld hat geschrieben:Im Forum konnte bis jetzt noch keiner sagen wie die Reihenfolge ist beim Aufruf.
Auf welche Reihenfolge spielst Du an? Reihenfolge der Parameter auf dem Stack?
Antworten