Hallo zusammen
ich möchte ein DLL aus python ansprechen.
Momentan stehe ich mir irgendwie selber auf dem Schlauch.
folgender Code gibt es in VB als Beispiel.
**************
Declare Sub AGL_GetVersion Lib "AGLink40.DLL" ( ByRef Major As Long, ByRef Minor As Long )
**************
Wie muss ich es unter Python lösen?
dieser Code findet zwar die DLL aber ein ansprechen der Funktion geht nicht.
***************
from ctypes import*
aglink = windll.LoadLibrary(r"C:\Program Files\DELTALOGIC\ACCON-AGLink\Redist\AGLink40.dll")
version= aglink.AGL_doGetVersion(0,0)
*************
es endet mit folgendem Fehler:
>>>
Traceback (most recent call last):
File "C:/Python26/aglink2.py", line 9, in <module>
version= aglink.AGL_doGetVersion(0,0)
File "C:\Python26\lib\ctypes\__init__.py", line 366, in __getattr__
func = self.__getitem__(name)
File "C:\Python26\lib\ctypes\__init__.py", line 371, in __getitem__
func = self._FuncPtr((name_or_ordinal, self))
AttributeError: function 'AGL_doGetVersion' not found
>>>
für eine kleine denkanstoss wäre ich dankbar.
für weitere Fragen bin ich da.
Grüsse und danke im Voraus
Thomas
Anbindung DLL an Python
Als nächstes dürfte dann das `ByRef` Probleme machen — die Funktion möchte keine Zahlen sondern Zeiger auf Zahlen.
-
- User
- Beiträge: 48
- Registriert: Samstag 2. Februar 2013, 18:52
Besten Dank
Ja es heisst AGL_GetVersion.
wieso weit suchen wenn es vor der Haustüre liegt.
Trotzdem Besten Dank
das mit dem By Val hat sich auch erledigt.
Ja es heisst AGL_GetVersion.
wieso weit suchen wenn es vor der Haustüre liegt.
Trotzdem Besten Dank
das mit dem By Val hat sich auch erledigt.
-
- User
- Beiträge: 48
- Registriert: Samstag 2. Februar 2013, 18:52
So nun brauche ich doch Pointer:
Die DLL erwartet ein Integer als Pointer im Speicherbereich und gibt diesen auch wieder so zurück.
Wie muss ich den Pointer in Python als Int aufbereiten dass es in der DLL zur verfügung steht und das ganze auch noch zurück?
Thomas
Die DLL erwartet ein Integer als Pointer im Speicherbereich und gibt diesen auch wieder so zurück.
Wie muss ich den Pointer in Python als Int aufbereiten dass es in der DLL zur verfügung steht und das ganze auch noch zurück?
Thomas
@thomasgull: Ich glaube es ist besser eine formale Signatur zu sehen statt aus dem Text zu raten was da genau gefordert ist.
-
- User
- Beiträge: 48
- Registriert: Samstag 2. Februar 2013, 18:52
Ich habe folgendes versucht:
erhalte als Ergebniss:
als C-Vorlage habe ich folgendes:
C/C++-Syntax:
Parameter:
DevNr Die Nummer des Devices
PlcNr Nummer des Busteilnehmers
ConnNr Verbindungshandle
Timeout Der zu verwendende Timeoutwert
UserVal Wert zur freien Verwendung
Code: Alles auswählen
from ctypes import *
a=c_int(10)
pA=byref(a)
print pA
erhalte als Ergebniss:
Code: Alles auswählen
IDLE 2.6.5 ==== No Subprocess ====
>>>
<cparam 'P' (014FA3C8)>
>>>
als C-Vorlage habe ich folgendes:
C/C++-Syntax:
Code: Alles auswählen
int WINAPI AGL_PLCConnect( int DevNr, int PlcNr, int *ConnNr, int Timeout, LONG_PTR UserVal );
Parameter:
DevNr Die Nummer des Devices
PlcNr Nummer des Busteilnehmers
ConnNr Verbindungshandle
Timeout Der zu verwendende Timeoutwert
UserVal Wert zur freien Verwendung
Zuletzt geändert von Anonymous am Montag 17. November 2014, 20:36, insgesamt 1-mal geändert.
Grund: Quelltexte in Code-Tags gesetzt.
Grund: Quelltexte in Code-Tags gesetzt.
@thomasgull: Was hast Du denn da jetzt ”versucht”? Das Ergebnis von `byref()` auszugeben bringt ja nichts, zumal das ja eh nur zur Übergabe als Parameter beim Aufruf einer C-Funktion taugt. Das wird man also eigentlich immer nur im Zusammenhang mit so einem Aufruf sehen. Also bei der gezeigten C-Funktion beim `ConnNr`-Argument und beim `UserVal`.
-
- User
- Beiträge: 48
- Registriert: Samstag 2. Februar 2013, 18:52
Ok war auch nur so ein Kurztest was in der Übergabe steht.
Nun die DLL bearbeitet den übergebenen Wert und gibt ihn an gleicher Speicherposition zurück.
Nun welche Funktion empfiehlt sich für solche Transaktionen?
Danke
Nun die DLL bearbeitet den übergebenen Wert und gibt ihn an gleicher Speicherposition zurück.
Nun welche Funktion empfiehlt sich für solche Transaktionen?
Danke
@thomasgull: `byref()`. Ist schneller/leichtgewichtiger als `pointer()` was man auch nehmen könnte.
-
- User
- Beiträge: 48
- Registriert: Samstag 2. Februar 2013, 18:52
danke
welches wäre die "genenfunktion" um aus der Pointervariable wieder den wert zu lesen?
Thomas
welches wäre die "genenfunktion" um aus der Pointervariable wieder den wert zu lesen?
Thomas
@thomasgull: Das hat mit Pointern doch gar nichts zu tun. Die Wertobjekte haben ein `value`-Attribut. Ansonsten wenn Du tatsächlich mal irgendwo Pointer hast, die haben ein `content`-Attribut.
-
- User
- Beiträge: 48
- Registriert: Samstag 2. Februar 2013, 18:52
also mit byref kann ich den zürückgeschrieben Wert ja nicht mehr lesen oder sehe ich das falsch?
@thomasgull: Du übergibst `byref()` doch irgendein Objekt das ein C-Wert repräsentiert. Das musst Du an einen Namen binden, dann kannst Du da doch hinterher problemlos drauf zugreifen. Sagen wir Du hast eine C-Bibliothek `some_library` und da gibt es eine Funktion mit folgender Signatur: ``void multiply_by_two(int *argument_and_result)``:
Code: Alles auswählen
x = ctypes.c_int(42)
some_library.multiply_by_two(byref(x))
print x.value # -> 84
-
- User
- Beiträge: 48
- Registriert: Samstag 2. Februar 2013, 18:52
Besten Dank
Problematik war dass ich nur from Ctypes import* gemacht habe und da hat er beim Ausdruck x.value gemeckert.
So das funktioniert einwandfrei, nun wie geht das auf der Stringebene?
üBergeben mit:
Funktioniert anscheinend
wie muss ich es wieder auslesen?
wenn ich einen Versuch direkt mache ( mit byval in eine Variable und dort wieder als Variable.value auslese klappt es) anscheined modifiziert die DLL irgendwas.
meldet es invalid String pointer 0xirgendwas
Danke
Thomas
Problematik war dass ich nur from Ctypes import* gemacht habe und da hat er beim Ausdruck x.value gemeckert.
So das funktioniert einwandfrei, nun wie geht das auf der Stringebene?
üBergeben mit:
Code: Alles auswählen
mlfb=c_char_p("xxx")
mlfbref=byref(mlfb)
wie muss ich es wieder auslesen?
wenn ich einen Versuch direkt mache ( mit byval in eine Variable und dort wieder als Variable.value auslese klappt es) anscheined modifiziert die DLL irgendwas.
Code: Alles auswählen
x=mlfb.value
Danke
Thomas
@thomasgull: Den Satz mit „byval” (was ist das?) habe ich nicht verstanden. Ansonsten nimm die Meldung einfach mal so wie sie da steht: irgendwie bekommst Du da einen Zeiger rein der ungültig ist.
Ansonsten sind Beschreibungen wie „hat er beim Ausdruck x.value gemeckert” oder „meldet es invalid String pointer 0xirgendwas” sehr ungenau. Wenn es Ausnahmen gibt, dann wäre der komplette Traceback und der dazugehörige Quelltext in der Regel hilfreicher für helfende.
Kann es sein, dass die Funktion irgendwie auf eine andere Weise anzeigt, dass ein Fehler aufgetreten ist und man deshalb den Zeiger gar nicht erst benutzen darf? Wird da überhaupt ein Zeiger auf einen Zeiger auf ``char`` erwartet? Also ist die C-Signatur an der Stelle wirklich ``char **argument``?
Ansonsten sind Beschreibungen wie „hat er beim Ausdruck x.value gemeckert” oder „meldet es invalid String pointer 0xirgendwas” sehr ungenau. Wenn es Ausnahmen gibt, dann wäre der komplette Traceback und der dazugehörige Quelltext in der Regel hilfreicher für helfende.
Kann es sein, dass die Funktion irgendwie auf eine andere Weise anzeigt, dass ein Fehler aufgetreten ist und man deshalb den Zeiger gar nicht erst benutzen darf? Wird da überhaupt ein Zeiger auf einen Zeiger auf ``char`` erwartet? Also ist die C-Signatur an der Stelle wirklich ``char **argument``?
-
- User
- Beiträge: 48
- Registriert: Samstag 2. Februar 2013, 18:52
Ok folgender Code:
Antwort:
Danke
Code: Alles auswählen
#mlfb lesen
mlfbnr=ctypes.c_char_p("xxxxxxxxxxxxxxxxxxxx")
mlfbnrref=byref(mlfbnr)
timeout=2000
egal=0
print mlfbnr.value
mlfb= aglink.AGL_ReadMLFBNr(connectNrRet,mlfbnrref,timeout,egal)
if mlfb ==0:
print "MLFB erfolgreich"
x=mlfbnr.value
print x
else:
error=" "
errtxt= aglink.AGL_GetErrorMsg(mlfb,error,256)
print error
Code: Alles auswählen
xxxxxxxxxxxxxxxxxxxx
MLFB erfolgreich
Traceback (most recent call last):
File "C:\Python26\DLLs\aglink3.py", line 112, in <module>
x=mlfbnr.value
ValueError: invalid string pointer 0x37534536
>>>
@thomasgull: Ein Pointer dessen Bytewerte alle im ASCII-Bereich liegen und bei etwas das eine ”Nummer” ermittel zwei ASCII-Ziffern enthält ist zumindest verdächtig. Ich bleibe bei meiner Vermutung das hier kein Zeiger auf einen Zeiger auf ``char`` erwartet wird sondern nur ein Zeiger auf ``char``. Und Du möchtest da vielleicht auch besser keinen `c_char_p()`-Wert übergeben der auf eine eigentlich unveränderbare Python-Zeichenkette zeigt. Da können böse Sachen passieren. `c_buffer()` oder `create_string_buffer()` verwendet man dafür.
@Sirius: Da wird ein Zeiger auf ein Byte-Array der Länge 21 erwartet wo ein Nullterminierter String reingeschrieben wird, laut API-Dokumentation. → http://www.sumelco.com/wp-content/uploa ... k_4_HB.pdf (Seite 156):
@Sirius: Da wird ein Zeiger auf ein Byte-Array der Länge 21 erwartet wo ein Nullterminierter String reingeschrieben wird, laut API-Dokumentation. → http://www.sumelco.com/wp-content/uploa ... k_4_HB.pdf (Seite 156):
Code: Alles auswählen
int WINAPI AGL_ReadMLFBNr( int ConnNr, LPMLFB MLFBNr, int Timeout, long UserVal );
typedef struct tagMLFB
{
BYTE MLFB[21]; // MLFB number as a zero-terminated string
} MLFB, *LPMLFB;
-
- User
- Beiträge: 48
- Registriert: Samstag 2. Februar 2013, 18:52
Richtig die DLL erwartet eine String mit 21 Zeichen.