[英]Using Python Ctypes to pass struct pointer to a DLL function
I am attempting to access a function in a DLL file using Python ctypes. 我正在尝试使用Python ctypes访问DLL文件中的函数。 The provided function description is below.
提供的功能说明如下。
Prototype: Picam_ConnectDemoCamera( PicamModel model,
const pichar* serial_number,
PicamCameraID* id )
Description: Virtually connects the software-simulated 'model' with 'serial_number'
and returns the camera id in `_id_`
Notes: `_id_` is optional and can be null
The function references a few variable types defined in the DLL. 该函数引用DLL中定义的一些变量类型。 These variables are described next
接下来介绍这些变量
PicamModel
Type: enum
Description: The camera model.
PicamCameraID
Type: Struct
- PicamModel model: _model_ is the camera model
- PicamComputerInterface computer_interface: computer_interface is the method of
communication
- pichar sensor_name [PicamStringSize_SensorName]: sensor_name contains the name of
the sensor in the camera
- pichar serial_number [PicamStringSize_SerialNumber]: serial_number contains the
unique serial number of the camera
Note that'pichar' is defined in one of the provided header files as follows: 请注意,在提供的头文件之一中定义了“ pichar”,如下所示:
typedef char pichar; /* character native to platform
This seems straightforward, but isn't working out for me for some reason. 这似乎很简单,但由于某种原因对我而言却没有解决。
My understanding is as follows: I pass the function three variables: 我的理解如下:我向函数传递了三个变量:
1) a model
, which is really an enum
. 1)一个
model
,它实际上是一个enum
。 I'm told that python ctypes doesn't inherently support enums, and so I am passing it an integer, 2, which maps to a particular model type. 有人告诉我python ctypes本质上不支持枚举,因此我将其传递给整数2,该整数映射到特定的模型类型。
2) a pointer to a serial number (I can make this up: an arbitrary string) 2)指向序列号的指针(我可以组成一个:任意字符串)
3) A pointer to PicamCameraID
, a variable type defined within the DLL, based on the struct
type 3)指向
PicamCameraID
的指针,该指针是DLL中定义的基于struct
类型的变量类型
After reading through SO I found a few good starting points, but am still running out of luck. 读完SO之后,我找到了一些很好的起点,但是仍然运气不佳。 Here's my best shot so far
到目前为止,这是我最好的镜头
def pointer(x):
PointerToType = ctypes.POINTER(type(x))
ptr = ctypes.cast(ctypes.addressof(x), PointerToType)
return ptr
class PicamCameraID(ctypes.Structure):
pass
PicamCameraID._fields_=[("model",ctypes.c_int),
("computer_interface",ctypes.c_int),
("sensor_name",ctypes.c_char_p),
("serial_number",ctypes.c_char_p)]
myid = PicamCameraID()
model = ctypes.c_int(2)
serialnum = ctypes.c_char_p('asdf')
print picam.Picam_ConnectDemoCamera(model, pointer(serialnum), ctypes.byref(myid))
As you can hopefully see, I'm trying to create the variable type that corresponds to the PicamCameraID
struct defined in the DLL. 如您
PicamCameraID
,我正在尝试创建与DLL中定义的PicamCameraID
结构相对应的变量类型。 My intuition was to use the ctypes.pointer
command to reference this when passing the argument to the function, but I found indications to use ctypes.byref
instead elsewhere . 我的直觉是在将参数传递给函数时使用
ctypes.pointer
命令引用此参数,但是我发现在其他地方使用ctypes.byref
指示。
The code runs without error (returns 0), however, I get varying results when I try to access the properties of the struct PicamCameraID
: 代码运行无错误(返回0),但是,当我尝试访问结构
PicamCameraID
的属性时,得到的结果却有所不同:
myid.model
returns "2" which is great that's what I specified myid.computer_interface
returns "1" which is fine myid.model
返回“ 2”,这是我指定的值myid.computer_interface
返回“ 1”,这很好
BUT the problem is myid.serial_number
returns 但是问题是
myid.serial_number
返回
Traceback (most recent call last): File "<pyshell#28>", line 1, in
<module>
myid.serial_number ValueError: invalid string pointer 0x2820303031207820
and myid.sensor_name
returns: 和
myid.sensor_name
返回:
Traceback (most recent call last): File "<pyshell#29>", line 1, in
<module>
myid.sensor_name ValueError: invalid string pointer 0x3034333120563245
For some reason these strings aren't being properly populated? 由于某种原因,这些字符串没有正确填充?
Any ideas would be much appreciated, I am a novice to python ctypes (and c) 任何想法将不胜感激,我是python ctypes(和c)的新手
Kind regards 亲切的问候
Addition June 1 2013 增加2013年6月1日
typedef enum PicamStringSize {
PicamStringSize_SensorName = 64,
PicamStringSize_SerialNumber = 64,
PicamStringSize_FirmwareName = 64,
PicamStringSize_FirmwareDetail = 256 } PicamStringSize;
typedef struct PicamCameraID {
PicamModel model;
PicamComputerInterface computer_interface;
pichar sensor_name[PicamStringSize_SensorName];
pichar serial_number[PicamStringSize_SerialNumber];
} PicamCameraID;
Your definition of PicamCameraID structure is incorrect: sensor_name
and serial_number
are arrays : 您对PicamCameraID结构的定义不正确:
sensor_name
和serial_number
是arrays :
"""
struct PicamCameraID {
PicamModel model;
PicamComputerInterface computer_interface;
pichar sensor_name[PicamStringSize_SensorName];
pichar serial_number[PicamStringSize_SerialNumber];
};
"""
import ctypes as c
PicamStringSize_SensorName = PicamStringSize_SerialNumber = 64
PicamModel = PicamComputerInterface = c.c_int
pichar = c.c_char
class PicamCameraID(c.Structure):
_fields_ = [("model", PicamModel),
("computer_interface", PicamComputerInterface),
("sensor_name", pichar * PicamStringSize_SensorName),
("serial_number", pichar * PicamStringSize_SerialNumber)]
It seems the second argument is just a string, so you don't need to apply pointer()
to it. 似乎第二个参数只是一个字符串,因此您不需要对其应用
pointer()
。 Here's the ctypes
prototype for Picam_ConnectDemoCamera()
function: 这是
Picam_ConnectDemoCamera()
函数的ctypes
原型:
"""
Picam_ConnectDemoCamera(PicamModel model, const pichar* serial_number,
PicamCameraID* id)
"""
pichar_p = c.c_char_p # assume '\0'-terminated C strings
Picam_ConnectDemoCamera.argtypes = [PicamModel, pichar_p,
c.POINTER(PicamCameraID)]
Picam_ConnectDemoCamera.restype = c.c_int # assume it returns C int
To call it: 调用它:
picam_id = PicamCameraID()
rc = Picam_ConnectDemoCamera(2, "serial number here", c.byref(picam_id))
print(rc)
print(picam_id.sensor_name.value) # C string
print(picam_id.sensor_name.raw) # raw memory
Likely, you're not entering the exact structure fields in the exact same order. 您可能没有以完全相同的顺序输入确切的结构字段。 If you don't, then you usually get random data or segfaults.
如果不这样做,那么通常会得到随机数据或段错误。 To access a library with ctypes, you usually need to look inside the header (.h file) to copy the exact structure definition.
要访问具有ctypes的库,通常需要查看标头(.h文件)的内部,以复制确切的结构定义。 Alternatively, use cffi with ffi.verify() if you don't want to depend on the precise layout.
另外,如果您不想依赖精确的布局, 请将cffi与ffi.verify()结合使用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.