ctypes.Structure POINTER

Python in C/C++ embedden, C-Module, ctypes, Cython, SWIG, SIP etc sind hier richtig.
Antworten
Benutzeravatar
lightos
User
Beiträge: 39
Registriert: Montag 12. Dezember 2011, 19:39
Wohnort: Raum Bruchsal
Kontaktdaten:

Es gelingt mir nicht, ctypes-Strukturen über Pointer-Referenzen zu verschachteln:

class A(ctypes.Structure):
_fields_ .....



class B(ctypes.Structure):
_fields_ = [("RefA", ctypes.POINTER(A)), .... ]

def __init__(self, obj, ...)
self.RefA = ctypes.pointer(obj) # wobei hier dann obj self aus A ist


Das Anlagen von A und B klappt.
Nun soll aber eine create-Funktion von A() eine Instanz von b=B() erzeugen und sich selbst in b als Referenz eintragen.
Naheliegend war, einfach "self" zu übergeben, und dies dann im Struct der Variablen RefA zuzuweisen.
Geht aber nicht!

Nach der Zuweisung enthält RefA eine riesen Liste von Einträgen. Rekursion?
Benutzeravatar
lightos
User
Beiträge: 39
Registriert: Montag 12. Dezember 2011, 19:39
Wohnort: Raum Bruchsal
Kontaktdaten:

Ergänzung:

Das Problem sieht man nur im Debugger (PTVS in VS2013).
Nach der Zuweisung des Pointers enthält die Structure unzählige [0][1][2]..... Warum?

Hab das dazu nochmal aufgedrennt und erst den Typ mit ctypes.POINTER erzeugt. Danach das Python-Struct Objekt von diesem Typ und dann sind hier dann bereits die vielen Array-Elements drin.

"contents" und [0] sind identisch. Die Werte sehen gut aus. Aber ab [1][2] wiederholt sich das Ganze mit Zufallswerten.
Könnte das auch noch ein Problem in PTVS sein?
BlackJack

@lightos: `ctypes` lässt den Benutzer einen Pointer genau wie C auch als Array benutzen/ansehen.
Benutzeravatar
lightos
User
Beiträge: 39
Registriert: Montag 12. Dezember 2011, 19:39
Wohnort: Raum Bruchsal
Kontaktdaten:

Danke für die Rückmeldung. Trotzdem strange!
Warum ein Array. Die Adresse ist ein Pointer auf eine struct.

ZUr Sicherheit ein kleines Sample:

Code: Alles auswählen

import ctypes


class UsbPort(ctypes.Structure):
    _fields_ = [
        ("ResourceType", ctypes.c_uint),
        ("Index", ctypes.c_uint8),
        ("PhysicalLayer", ctypes.c_uint),
        ("DeviceInterfaces", ctypes.c_uint16),
        ("StreamingIfEpOutCount", ctypes.c_uint8),
        ("StreamingIfEpInCount", ctypes.c_uint8)
        ]

    def __init__(self, index, phyLayer, devInterfaces, streamEpOutCount, streamEpInCount):
        """initialize instance"""
        self.ResourceType = 0
        self.Index = ctypes.c_uint8(index)
        self.PhysicalLayer = ctypes.c_uint(phyLayer)
        self.DeviceInterfaces = ctypes.c_uint16(devInterfaces)
        self.StreamingIfEpOutCount = ctypes.c_uint8(streamEpOutCount)
        self.StreamingIfEpInCount = ctypes.c_uint8(streamEpInCount)
        self.sockets = []

    def create_socket(self, direction, dataType, endpointAddr, framesPerTransfer):
        socket = UsbSocket(self, direction, dataType, endpointAddr, framesPerTransfer)
        if socket != None:
            self.sockets.append(socket)
        return socket


class UsbSocket(ctypes.Structure):
    _fields_ = [
        ("ResourceType", ctypes.c_uint),
        ("UsbPortObjPtr", ctypes.POINTER(UsbPort)),
        ("Direction", ctypes.c_uint),
        ("DataType", ctypes.c_uint),
        ("EndpointAddr", ctypes.c_uint8),
        ("FramesPerTransfer", ctypes.c_uint16)
        ]

    def __init__(self, usbPortObj, direction, dataType, endpointAddr, framesPerTransfer):
        """initialize default instance"""
        self.ResourceType = 1
        PortType = ctypes.POINTER(UsbPort)
        portobj = PortType(usbPortObj)
        self.UsbPortObjPtr = portobj
        self.Direction =  ctypes.c_uint(direction)
        self.DataType = ctypes.c_uint(dataType)
        self.EndpointAddr = ctypes.c_uint8(endpointAddr)
        self.FramesPerTransfer = ctypes.c_uint16(framesPerTransfer)

port = UsbPort(0, 1,2,3,4)
socket = port.create_socket(0,1,2,512)

print(port)
print(socket)
print(socket.UsbPortObjPtr)
print('contents: {0}'.format(socket.UsbPortObjPtr.contents))
print('Array_0: {0}'.format(socket.UsbPortObjPtr[0]))
print('Array_1: {0}'.format(socket.UsbPortObjPtr[1]))

Wie groß soll das Array hier sein? Im Debugger geht das "unendlich" weit und dauert etwas beim Aufbau des Fensters.
Ist das wirklich korrekt und liegt an der internen ctypes-Struktur?
Der Abstand im Array (Pointer-Adressen) ist genau die Größe der struct.


Danke,
lightos
BlackJack

@lightos: Ein Pointer auf einen Typ kann man in C auch immer als Array von diesem Typ verwenden. Auch wenn da gar kein Array ist, dann besteht das Array nur aus dem einen Element auf das der Pointer zeigt. Man kann trotzdem auf Daten zugreifen die im Speicher dahinter liegen als wäre es ein längeres Array denn es wird zur Laufzeit keine Bereichsüberprüfung gemacht. Arrays beinhalten in C zur Laufzeit ja auch keine Information wieviele Elemente sie enthalten, darum muss man neben dem Zeiger auf den Arrayanfang normalerweise bei Funktionsaufrufen auch die Anzahl als eigenes Argument mit übergeben oder man hat am Arrayende einen speziellen Wert an dem man erkennen kann das es zuende ist. Zum Beispiel wird bei einem Array mit Pointern gerne der NULL-Pointer als Endkennzeichen verwendet.
Benutzeravatar
lightos
User
Beiträge: 39
Registriert: Montag 12. Dezember 2011, 19:39
Wohnort: Raum Bruchsal
Kontaktdaten:

Damit wäre die einfach Antwort: Alles Gut?
Mit C habe ich hier keine Probleme, da man natürlich im Debugger alle Adressen prüfen kann (auch außerhalb).
Erklärt meiner Ansicht nach nicht, warum der Debugger (PTVS in VS2013) in Python das so darstellt. Er kennt den struct und die Größe.

Aber gut. Hauptsache ist ja, dass der ctypes-Wrapper OK ist.

Danke,
lightos
BlackJack

@lightos: Der Debugger wird bei indexierbaren Typen wahrscheinlich einfach mal testen ob man die mit ganzen Zahlen Indexieren kann, und das geht, und dann wird halt probiert wie weit das geht, in diesem Fall ”undendlich”.

Und welche Grösse kennt der Debugger? Die Grösse von dem Array welches keines ist kennt der nicht. ``len(socket.UsbPortObjPtr)`` wird eine Fehlermeldung liefern, dass man von dem Objekt keine Länge abfragen kann.
Antworten