Verständnisfrage zu ctypes/DLL/struct

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Gesperrt
Benutzeravatar
Damaskus
Administrator
Beiträge: 919
Registriert: Sonntag 6. März 2005, 20:08
Wohnort: Schwabenländle

Dienstag 29. April 2008, 14:27

Hi,
ich hab mal eine Verständnisfrage zu ctypes und einbinden von DLLs in Python.
In der Doku zu der verwendeten DLL (XL Driver Library http://www.vector-worldwide.com/vi_xl_d ... ,2816.html) steht folgendes:
C Syntax
XLstatus xlGetDriverConfig(XLdriverConfig *pDriverConfig)
Description
Allows reading out more detailed information about the used hardware. This function can be called at any time after a successfully xlOpenDriver. After each call the result describes the current state of the driver configuration.
Input Parameters
XLdriverConfig
Points to a user buffer for the information, which the driver returns. See details below for further information.
Return Value
Returns an error code.
XLdriverConfig
The driver returns the following structure containing the information:

Syntax

Code: Alles auswählen

typedef struct s_xl_driver_config {
unsigned int dllVersion; 
unsigned int channelCount; 
unsigned int reserved[10]; 
XLchannelConfig channel[XL_CONFIG_MAX_CHANNELS];
} XLdriverConfig;
XLchannelConfig
The following sub structure is used in structure XLdriverConfig (above-mentioned).

Code: Alles auswählen

typedef struct s_xl_channel_config {
char name [XL_MAX_LENGTH + 1];
unsigned char hwType;
unsigned char hwIndex;
unsigned char hwChannel;
unsigned short transceiverType;
unsigned int transceiverState;
unsigned char channelIndex;
XLuint64 channelMask;
unsigned int channelCapabilities;
unsigned int channelBusCapabilities;
unsigned char isOnBus;
unsigned int connectedBusType;
XLbusParams busParams;
unsigned int driverVersion;
unsigned int interfaceVersion;
unsigned int raw_data[10];
unsigned int serialNumber;
unsigned int articleNumber;
char transceiverName [XL_MAX_LENGTH + 1];
unsigned int specialCabFlags;
unsigned int dominantTimeout;
unsigned int reserved[8];
} XLchannelConfig;
usw....
Wenn ich die Funktion der DLL richtig verstanden hab, dann bildet mir die DLL dieses struct automatisch.

Was muss ich an die Funktion von Python aus übergeben damit ich dieses struct und die Werte zurückbekomme?
Oder muss ich eine class die dieses struct enthält erstellen und diese dann übergeben. Dann wäre die Frage wie erstelle ich die geforderten "sub structure" und übergebe das ganze dann an die DLL.


Code: Alles auswählen

from ctypes import *

class test_struct(Structure):
    _fields_ = [
        ("dllVersion", POINTER(c_uint)),
        ("channelCount", c_uint),
        ("reserved[10]", c_uint),
        ("channel", c_void_p) #Hier sollte die Substructure sein
    ]

dll = windll.LoadLibrary("vxlapi.dll")

# Treiber laden
XLstatus = dll.xlOpenDriver()
print c_char_p(dll.xlGetErrorString(c_int(XLstatus))).value

# Channel Index
xlChannelIndex = c_int(dll.xlGetChannelIndex(c_int(15), c_int(-1), c_int(-1))).value

# Treiber Konfig
XLstatus = dll.xlGetDriverConfig()  # Diese Funktion braucht das Struct oder evtl. einen Pointer

# Treiber schliessen
XLstatus = dll.xlCloseDriver()
print c_char_p(dll.xlGetErrorString(c_int(XLstatus))).value
Für Tipps und Hilfe wäre ich Dankbar!

Gruß
Damaskus
BlackJack

Dienstag 29. April 2008, 14:37

Du musst eine Klasse für die Unterstruktur erstellen und dann an der entsprechenden Stelle ein Array von dieser Unterstruktur in die Config-Struktur anstatt des void-Pointers setzen.
Benutzeravatar
Damaskus
Administrator
Beiträge: 919
Registriert: Sonntag 6. März 2005, 20:08
Wohnort: Schwabenländle

Dienstag 29. April 2008, 15:01

Ungefähr so?

Code: Alles auswählen

from ctypes import *

class test_struct2(Structure):
    _fields_ = [
        ("name", c_char_p),
        ("hmType", c_uint),
        ("usw...", c_uint)
    ]

class test_struct(Structure):
    _fields_ = [
        ("dllVersion", POINTER(c_uint)),
        ("channelCount", c_uint),
        ("reserved[10]", c_uint),
        ("xlChannelConfig", test_struct2) # <-- so richtig?
    ]



dll = windll.LoadLibrary("vxlapi.dll")

# Treiber laden
XLstatus = dll.xlOpenDriver()
print c_char_p(dll.xlGetErrorString(c_int(XLstatus))).value

# Channel Index
xlChannelIndex = c_int(dll.xlGetChannelIndex(c_int(15), c_int(-1), c_int(-1))).value

# Treiber Konfig
XLstatus = dll.xlGetDriverConfig()  # <-- Und wie kommt das dann hier rein ?

# Treiber schliessen
XLstatus = dll.xlCloseDriver()
print c_char_p(dll.xlGetErrorString(c_int(XLstatus))).value
BlackJack

Dienstag 29. April 2008, 19:35

Naja es ist ein Array. Genau wie der Eintrag davor, da müsstest Du die eckigen Klammern im Namen weglassen und ein Array von `c_unit`\s statt nur einem einzigen angeben.
Benutzeravatar
Damaskus
Administrator
Beiträge: 919
Registriert: Sonntag 6. März 2005, 20:08
Wohnort: Schwabenländle

Donnerstag 1. Mai 2008, 11:22

Ok, soweit hab ich es jetzt verstanden und es funktioniert auch.

Allerdings steh ich jetzt vor einem neuen Problem.
Wie bilde ich folgendes C Struct ind Python ab:

Code: Alles auswählen

typedef struct { 
  unsigned int busType;
    union {
      struct {
        unsigned int bitRate;
        unsigned char sjw;
        unsigned char tseg1;
        unsigned char tseg2;
        unsigned char sam;
        unsigned char outputMode;
      }can;
      unsigned char raw[32];
    }data;
  } XLbusParams;
Gruß
Damaskus
BlackJack

Donnerstag 1. Mai 2008, 13:01

Da würde ich mich von innen nach aussen vorarbeiten. Das enthält ja zwei zusammengesetzte anonyme Datentypen, die keinen Namen per ``typedef`` bekommen. Das innerste ``struct`` für das Feld `can` und das ``union`` für `data`. Ungetestet:

Code: Alles auswählen

class _CanStruct(Structure):
    _fields_ = [('bitRate', c_uint),
                ('sjw', c_ubyte),
                ('tseg1', c_ubyte),
                ('tseg2', c_ubyte),
                ('sam', c_ubyte),
                ('outputMode', c_ubyte),]

class _DataUnion(Union):
    _fields_ = [('can', _CanStruct),
                ('raw', c_ubyte * 32)]

class XLbusParams(Structure):
    _fields_ = [('busType', c_uint),
                ('data', _DataUnion)]
Benutzeravatar
Damaskus
Administrator
Beiträge: 919
Registriert: Sonntag 6. März 2005, 20:08
Wohnort: Schwabenländle

Montag 5. Mai 2008, 15:11

Weils das Forum hier nicht mehr packt.

Teil II:
http://www.python-forum.de/topic-14543.html
Gesperrt