DLL mit ctypes ansprechen (typedef struct, typedef enum)
Verfasst: Montag 15. Juni 2020, 09:13
Hallo,
ich stehe gerade vor dem Problem eine DLL mithilfe von ctypes ansprechen zu müssen. Diese DLL hat viele verschiedene Attribute wovon ich die einfachen schon erfolgreich ansprechen konnte. Bei den etwas komplizierteren mit "typedef struct / enum" komme ich gerade nicht weiter.
Das ist der C-Code zum Ansprechen der DLL:
int32_t CAENDPP_API
CAENDPP_AddBoard(
int32_t handle,
CAENDPP_ConnectionParams_t connParams,
int32_t *boardId
);
//----------------
//Types Definition
//----------------
typedef struct {
CAENDPP_ConnectionType LinkType;
int32_t LinkNum;
int32_t ConetNode;
uint32_t VMEBaseAddress;
char ETHAddress[IP_ADDR_LEN + 1];
} CAENDPP_ConnectionParams_t;
//----------------
typedef enum {
CAENDPP_USB = 0,
CAENDPP_PCI_OpticalLink = 1,
CAENDPP_ETH = 2,
CAENDPP_Serial = 3,
} CAENDPP_ConnectionType;
//--------------------
//Constants Definition
//--------------------
#define IP_ADDR_LEN 255
Mein Versuch das Problem zu lösen sieht bisher so aus:
from PyQt5 import QtWidgets, uic, QtCore
from PyQt5.QtCore import (QCoreApplication, QObject, QRunnable, QThread,
QThreadPool, pyqtSignal)
from PyQt5.QtWidgets import QApplication, QWidget, QInputDialog, QLineEdit, QFileDialog
import sys
import time
from random import randint
import ctypes
from enum import IntEnum
def wrap_function(lib, funcname, restype, argtypes):
"""Simplify wrapping ctypes functions"""
func = lib.__getattr__(funcname)
func.restype = restype
func.argtypes = argtypes
return func
class CAENDPP_ConnectionType(IntEnum):
CAENDPP_USB = 0
CAENDPP_PCI_OpticalLink = 1
CAENDPP_ETH = 2
CAENDPP_Serial = 3
class ConnectionParams_t(ctypes.Structure):
_fields_ = [('LinkType', CAENDPP_ConnectionType),
('LinkNum', ctypes.c_int),
('ConetNode', ctypes.c_int),
('VMEBaseAddress', ctypes.c_uint),
('ETHAddress', ctypes.c_char * 256)]
def __init__(self, ha, hb, hc, hd, he):
hb_c = (ctypes.c_int * 1)(*hb)
hc_c = (ctypes.c_int * 1)(*hc)
hd_c = (ctypes.c_uint * 1)(*hd)
he_c = (ctypes.c_char * 256)(*he)
super(Histotype, self).__init__(ha, hb_c, hc_c, hd_c, he_c)
...
c_int_p = ctypes.POINTER(ctypes.c_int)
c_int_pp = ctypes.POINTER(c_int_p)
load = wrap_function(MyDllObject, 'CAENDPP_AddBoard', ctypes.c_int, [c_int_p, ctypes.POINTER(ConnectionParams_t),c_int_pp])
# Instantiate an int * pointer.
# Use byref to pass the address of the pointer.
d1 = ctypes.c_int
linktype = CAENDPP_ConnectionType
linknum = 1
conetnode = 2
vmebaseaddress = 3
ethaddress = ctypes.c_char * 256
d2 = ConnectionParams_t(linktype,linknum,conetnode,vmebaseaddress,ethaddress)
d3 = c_int_p()
DLLanswer = load(ctypes.byref(d1),ctypes.byref(d2),ctypes.byref(d3))
Ich bekomme bisher die Fehler-Meldung:
TypeError: second item in _fields_ tuple (index 0) must be a C type
Kann mir jemand helfen? Gern auch mit einer allgemeinen Lösung für die Übersetzung von "typedef struct" in Python ctypes.
Vielen Dank, euch!
ich stehe gerade vor dem Problem eine DLL mithilfe von ctypes ansprechen zu müssen. Diese DLL hat viele verschiedene Attribute wovon ich die einfachen schon erfolgreich ansprechen konnte. Bei den etwas komplizierteren mit "typedef struct / enum" komme ich gerade nicht weiter.
Das ist der C-Code zum Ansprechen der DLL:
int32_t CAENDPP_API
CAENDPP_AddBoard(
int32_t handle,
CAENDPP_ConnectionParams_t connParams,
int32_t *boardId
);
//----------------
//Types Definition
//----------------
typedef struct {
CAENDPP_ConnectionType LinkType;
int32_t LinkNum;
int32_t ConetNode;
uint32_t VMEBaseAddress;
char ETHAddress[IP_ADDR_LEN + 1];
} CAENDPP_ConnectionParams_t;
//----------------
typedef enum {
CAENDPP_USB = 0,
CAENDPP_PCI_OpticalLink = 1,
CAENDPP_ETH = 2,
CAENDPP_Serial = 3,
} CAENDPP_ConnectionType;
//--------------------
//Constants Definition
//--------------------
#define IP_ADDR_LEN 255
Mein Versuch das Problem zu lösen sieht bisher so aus:
from PyQt5 import QtWidgets, uic, QtCore
from PyQt5.QtCore import (QCoreApplication, QObject, QRunnable, QThread,
QThreadPool, pyqtSignal)
from PyQt5.QtWidgets import QApplication, QWidget, QInputDialog, QLineEdit, QFileDialog
import sys
import time
from random import randint
import ctypes
from enum import IntEnum
def wrap_function(lib, funcname, restype, argtypes):
"""Simplify wrapping ctypes functions"""
func = lib.__getattr__(funcname)
func.restype = restype
func.argtypes = argtypes
return func
class CAENDPP_ConnectionType(IntEnum):
CAENDPP_USB = 0
CAENDPP_PCI_OpticalLink = 1
CAENDPP_ETH = 2
CAENDPP_Serial = 3
class ConnectionParams_t(ctypes.Structure):
_fields_ = [('LinkType', CAENDPP_ConnectionType),
('LinkNum', ctypes.c_int),
('ConetNode', ctypes.c_int),
('VMEBaseAddress', ctypes.c_uint),
('ETHAddress', ctypes.c_char * 256)]
def __init__(self, ha, hb, hc, hd, he):
hb_c = (ctypes.c_int * 1)(*hb)
hc_c = (ctypes.c_int * 1)(*hc)
hd_c = (ctypes.c_uint * 1)(*hd)
he_c = (ctypes.c_char * 256)(*he)
super(Histotype, self).__init__(ha, hb_c, hc_c, hd_c, he_c)
...
c_int_p = ctypes.POINTER(ctypes.c_int)
c_int_pp = ctypes.POINTER(c_int_p)
load = wrap_function(MyDllObject, 'CAENDPP_AddBoard', ctypes.c_int, [c_int_p, ctypes.POINTER(ConnectionParams_t),c_int_pp])
# Instantiate an int * pointer.
# Use byref to pass the address of the pointer.
d1 = ctypes.c_int
linktype = CAENDPP_ConnectionType
linknum = 1
conetnode = 2
vmebaseaddress = 3
ethaddress = ctypes.c_char * 256
d2 = ConnectionParams_t(linktype,linknum,conetnode,vmebaseaddress,ethaddress)
d3 = c_int_p()
DLLanswer = load(ctypes.byref(d1),ctypes.byref(d2),ctypes.byref(d3))
Ich bekomme bisher die Fehler-Meldung:
TypeError: second item in _fields_ tuple (index 0) must be a C type
Kann mir jemand helfen? Gern auch mit einer allgemeinen Lösung für die Übersetzung von "typedef struct" in Python ctypes.
Vielen Dank, euch!