ctypes - POINTER oder c_void_p

Python in C/C++ embedden, C-Module, ctypes, Cython, SWIG, SIP etc sind hier richtig.
Antworten
myxin
User
Beiträge: 47
Registriert: Dienstag 10. Januar 2012, 16:57

Hallo,

ich möchte gerne eine Fremd-DLL benutzen und verstehe nicht ganzden Unterschied zwischen
POINTER und c_void_p

Die DLL Funktion erwartet eine Struktur namens callback_data

Code: Alles auswählen

class xorg_subject(Structure):                    # typedef struct xorg_subject
    _fields_ = [("text", c_char * 256)]           # char    text[256]

class callback_data(Structure):                   # typedef struct callback_data
    _fields_ = [("size", c_int),                  # int         size
                ("resData", c_void_p),            # void       *resData   
                ("subject", xorg_subject),        # struct xorg_subject   *subject
                ("reqData", POINTER(c_int))]      # void       *reqData
Was ist die richtige Art *resData bzw *reqData zu definieren?
Beides scheint zu funktionieren.

Desweitern, ruft die DLL Funktion meinen Callback asynchron auf.
Was sind geeignete Mittel um auf diesen Callback zu warten bevor
das Skript weiterlaufen soll?

Danke
Claudia
deets

funktionieren tut prinzipiell beides, weil ein Pointer nunmal ein Pointer ist. Wahlweise 32 oder 64 Bit. c_void_p ist halt fuer den Standardfall schonmal vordefiniert, entspricht also POINTER(None).

Und was die asynchronitaet angeht - solange du uns da nicht etwas mehr drueber verraetst, kann man dazu nix sagen, aber aus dem Bauch heraus: gar nicht. Sofern die Bibliothek keine eigenen Threads verwendet (was ziemlicher Horror waere), wird dein callback synchron zu irgendwelche Bibliotheksaufrufen aufgerufen werden.
lunar

@myxin: "POINTER(c_int)" kannst Du dereferenzieren, sprich Du erhältst über dessen Attribut ".data" den Wert, auf den der Zeiger verweist, als Python-"int". Bei "c_void_p" geht das nicht, solche Objekte musst Du vor dem Dereferenzieren erst in einen konkreten Zeiger-Typ konvertieren. Ansonsten gibt es keine Unterschied, da Zeiger in C immer gleich groß sind.
BlackJack

@myxin: `POINTER()` ist eine Funktion die aus einem Objekt, das einen C-Datentyp repräsentiert, ein Objekt erstellt, das einen Pointertyp auf den übergebenen Typ repräsentiert. `c_void_p` repräsentiert einen Pointer-Typ auf *irgendwas*. Wenn man ein Exemplar davon hat, und an die Daten dahinter kommen möchte, muss man vorher mit der `cast()`-Funktion zu dem Typ casten, den das Ding hinter dem Zeiger tatsächlich hat.

Die Definition von `callback_data.subject` ist IMHO falsch. Der will da keine `xorg_subject`-Struktur sondernen einen Zeiger auf eine solche Struktur.
myxin
User
Beiträge: 47
Registriert: Dienstag 10. Januar 2012, 16:57

Hallo,
@Alle vielen Dank für die Erklärungen.

@BlackJack, stimmt, da hatte ich auch rumprobiert da scheinen auch beide Varianten zu funktionieren,
sowohl "subject", xorg_subject als auch "subject", POINTER(xorg_subject)

@deets, so richtig viel weiß ich leider auch noch nicht, mir ist nur aufgefallen,
dass während der Tests meine CallbackFunktion ab und zu später zurückgekommen ist.
Ich hatte gedacht, dass python evtl. etwas ähnliches wie DoEvents von vb kennt.

Die Idee, etwas wie

Code: Alles auswählen

    Callback_not_returned = 1

    def myCallback():
        Callback_not_returned = 0

    def foo():
        while Callback_not_returned:
            DoEvents_von_python

        print 'callback returned'
Gruß
Claudia
deets

Natuerlich gibt es auch in Python event-loops. Aber nur explizit, wenn du zB ein GUI-Toolkit verwendest. Und solange deine Lib nicht mit sowas sich verheiratet (also zB eine Qt oder GTK-Erweiterung waere), koennte sie asynchronitaet nur durch Threads erzeugen.

Wie gesagt, ohne mehr Info kann man da nix zu sagen. Wozu ist denn der Callback da, und generell die Lib?
lunar

@deets: "xorg_subject" und "reqData" lassen mich vermuten, dass es sich um irgendetwas aus dem X.org-Umfeld handelt, also Xlib oder irgendeine darauf aufbauende Bibliothek.
myxin
User
Beiträge: 47
Registriert: Dienstag 10. Januar 2012, 16:57

Hallo,

@lunar, @deets
Es geht um Mess- und Regeltechnik.
Die dll erlaubte es mit, eine Interfacekarte bezüglich Messwerte abzufragen.
Den Hersteller gibt es leider nicht mehr. Ich habe nur ein laufendes TestProgram
und ein Headerdatei, von der ich nicht mal sicher bin, ob die nicht mein Vorgänger selbst erstellt hat.

Im Prinzip läuft es wie folgt,

mit der Funktion Connect bekomme ich Zugriff auf die Kartenlogik,
danach rufe ich verschiedene Testfunktionen auf, die
alle als Parameter, unter anderem, eine Callbackfunktion erwarten.
Bei allen Funktionen geschieht dies auch synchron, nur eine
Funktion, TestCr21, scheint den Callback entweder nicht
oder, was ich momentan vermute, verspätet aufzurufen.

Im Skript habe ich immer die gleiche Callbackfunktion.
An der kann es eigentlich nicht liegen, da die anderen 17 Funktionen
ohne Probleme laufen und auch diese Funktion den Returnwert rc=0 liefert,
was ich bis dato als erfolgreich aufgerufen wertete.
Bin ratlos was hier falsch läuft.

Ach ja, über den Callback bekomme ich dann die Messwerte,
genauer gesagt den Pointer resData, den ich dann
auf die zugehörige Struktur caste (die ich via Pointer reqData indentifizieren kann).

Besten Dank für Eure Hilfe
Claudia
BlackJack

@myxin: Hast Du denn den Typ von `callback_data.subject` mittlerweile korrigiert? Da funktionieren sicher *nicht* beide Varianten. Jedenfalls nicht wenn `subject` und `reqData` tatsächlich verwendet werden. Das kann bei C manchmal so aussehen, dass etwas funktioniert, weil es zur Laufzeit keine Typprüfung gibt und der Code dann irgendwelchen Unsinn macht, der im besten Fall sofort zu einem Programmabsturz führt, und im schlechteren Fall irgend wo Daten korrumpiert, die einem erst viel später auf die Füsse fallen.
myxin
User
Beiträge: 47
Registriert: Dienstag 10. Januar 2012, 16:57

@BlackJack, ja, ich habe wieder "subject", POINTER(xorg_subject) gemacht.
Hmm, ... stimmt, ich habe, als ich es geändert hatte, nicht wirklich auf Text zugegriffen,
sondern nur geschaut ob die Funktion mit rc==0 endet.
Muß ich am Montag nochmal genauer testen.

Danke
Claudia
myxin
User
Beiträge: 47
Registriert: Dienstag 10. Januar 2012, 16:57

@Alle - vielen Dank

Habe das Problem gefunden.
Es lag NATÜRLICH an meiner Dusseligkeit.
TestCr21 verlangt als einzige Funktion eine anderes Callbacklayout.
Einmal richtig defniert und schon funktioniert es.

Gruß
Claudia
Antworten