使用Python Ctypes将结构指针传递给DLL函数 [英] Using Python Ctypes to pass struct pointer to a DLL function
问题描述
我正在尝试使用Python ctypes访问DLL文件中的函数.提供的功能说明如下.
I am attempting to access a function in a DLL file using Python ctypes. 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
该函数引用DLL中定义的一些变量类型.接下来将对这些变量进行说明
The function references a few variable types defined in the 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
请注意,在提供的头文件之一中定义了"pichar",如下所示:
Note that'pichar' is defined in one of the provided header files as follows:
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)一个model
,它实际上是一个enum
.有人告诉我python ctypes本质上不支持枚举,因此我将其传递给整数2,该整数映射到特定的模型类型.
1) a model
, which is really an 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.
2)指向序列号的指针(我可以这样写:任意字符串)
2) a pointer to a serial number (I can make this up: an arbitrary string)
3)指向PicamCameraID
的指针,PicamCameraID
是DLL中定义的基于struct
类型的变量类型
3) A pointer to PicamCameraID
, a variable type defined within the DLL, based on the struct
type
通读SO之后,我发现了一些不错的起点,但是仍然运气不佳.这是到目前为止我最好的镜头
After reading through SO I found a few good starting points, but am still running out of luck. 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))
您可以看到,我正在尝试创建与DLL中定义的PicamCameraID
结构相对应的变量类型.我的直觉是在将参数传递给函数时使用ctypes.pointer
命令引用此函数,但是我发现使用ctypes.byref
而不是
As you can hopefully see, I'm trying to create the variable type that corresponds to the PicamCameraID
struct defined in the DLL. 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.
代码运行无错误(返回0),但是,当我尝试访问struct PicamCameraID
的属性时,得到的结果却有所不同:
The code runs without error (returns 0), however, I get varying results when I try to access the properties of the struct PicamCameraID
:
myid.model
返回"2",这很好,这是我指定的
myid.computer_interface
返回"1"就可以了
myid.model
returns "2" which is great that's what I specified
myid.computer_interface
returns "1" which is fine
但是问题,myid.serial_number
返回
Traceback (most recent call last): File "<pyshell#28>", line 1, in
<module>
myid.serial_number ValueError: invalid string pointer 0x2820303031207820
和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?
任何想法都将不胜感激,我是python ctypes(和c)的新手
Any ideas would be much appreciated, I am a novice to python ctypes (and c)
亲切的问候
2013年6月1日添加
Addition June 1 2013
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;
推荐答案
您对PicamCameraID结构的定义不正确:sensor_name
和serial_number
是
Your definition of PicamCameraID structure is incorrect: sensor_name
and serial_number
are 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)]
似乎第二个参数只是一个字符串,因此您无需对其应用pointer()
.这是Picam_ConnectDemoCamera()
函数的ctypes
原型:
It seems the second argument is just a string, so you don't need to apply pointer()
to it. Here's the ctypes
prototype for Picam_ConnectDemoCamera()
function:
"""
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
调用它:
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
这篇关于使用Python Ctypes将结构指针传递给DLL函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!