使用Python Ctypes将结构指针传递给DLL函数

使用Python Ctypes将结构指针传递给DLL函数,python,pointers,struct,ctypes,Python,Pointers,Struct,Ctypes,我正在尝试使用Python ctypes访问DLL文件中的函数。提供的功能描述如下 原型:Picam_ConnectDemoCamera(PicamModel模型, const pichar*序列号, PicamCameraID*id) 描述:虚拟连接软件模拟的“模型”和“序列号” 并在`\u id中返回相机id_` 注意:`u id`是可选的,可以为空 该函数引用DLL中定义的几个变量类型。下面将描述这些变量 PicamModel 类型:枚举 描述:相机型号。 皮卡美拉德 类型:Struct

我正在尝试使用Python ctypes访问DLL文件中的函数。提供的功能描述如下

原型:Picam_ConnectDemoCamera(PicamModel模型,
const pichar*序列号,
PicamCameraID*id)
描述:虚拟连接软件模拟的“模型”和“序列号”
并在`\u id中返回相机id_`
注意:`u id`是可选的,可以为空
该函数引用DLL中定义的几个变量类型。下面将描述这些变量

PicamModel
类型:枚举
描述:相机型号。
皮卡美拉德
类型:Struct
-PicamModel模型:_model_u是相机模型
-PicamComputerInterface计算机接口:计算机接口是
通信
-pichar传感器名称[PicamStringSize\u传感器名称]:传感器名称包含
摄像机中的传感器
-pichar序列号[PicamString\u序列号]:序列号包含
相机的唯一序列号
请注意,“pichar”在提供的一个头文件中定义如下:

typedef          char   pichar; /* character native to platform   
这似乎很简单,但由于某些原因,对我来说行不通

我的理解如下:我传递函数三个变量:

1) 一个
模型
,它实际上是一个
枚举
。我被告知python ctypes本质上不支持枚举,因此我将向它传递一个整数2,它映射到一个特定的模型类型

2) 指向序列号的指针(我可以组成:任意字符串)

3) 指向
PicamCameraID
的指针,该指针是DLL中基于
struct
类型定义的变量类型

经过通读,我找到了一些好的起点,但我仍然运气不佳。这是我迄今为止最好的一张照片

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
struct相对应的变量类型。我的直觉是在将参数传递给函数时使用
ctypes.pointer
命令引用它,但我发现使用
ctypes.byref
的指示

代码运行时没有错误(返回0),但是,当我尝试访问结构的属性时,会得到不同的结果

myid.model
返回“2”,这是我指定的
myid.computer\u接口
返回“1”,这很好

但是问题是
myid。序列号
返回

Traceback (most recent call last):   File "<pyshell#28>", line 1, in
<module>
   myid.serial_number ValueError: invalid string pointer 0x2820303031207820
出于某种原因,这些字符串没有正确填充

如果您有任何想法,我将不胜感激,因为我是PythoncTypes(和c)的新手

问候

新增2013年6月1日

typedef枚举PicamStringSize{
PicamStringSize_SensorName=64,
PicamStringSize_SerialNumber=64,
PicamStringSize_FirmwareName=64,
PicamStringSize_firmwaredeail=256}PicamStringSize;
类型定义结构PicamCameraID{
PicamModel模型;
PICAMC计算机接口计算机接口;
pichar传感器名称[PicamString传感器名称];
pichar序列号[PicamString序列号];
}皮卡美拉德;

很可能,您没有以完全相同的顺序输入确切的结构字段。如果没有,则通常会得到随机数据或故障。要使用ctypes访问库,通常需要查看头(.h文件)内部以复制准确的结构定义。或者,如果您不想依赖精确的布局,请与ffi.verify()一起使用。

您对PicamCameraID结构的定义不正确:
传感器名称和
序列号是:

第二个参数似乎只是一个字符串,因此不需要对其应用
pointer()
。以下是Picam\u 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
称之为:

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

什么是比哈尔
?如何确定字符串的大小?如果您直接传递
serialnum
而不调用
pointer()
会发生什么?J.F.--感谢您的响应。我的头文件告诉我以下内容:typedef char pichar;/*字符本机到平台换句话说,我相信这只是对字符的重新映射?嗨,Armin——我刚刚从头文件中添加了一些文本,我认为这符合您的建议。可能是因为我的“sensor_name”字符串没有指定正确的长度,因此我的两个字符串基本上混在一起,数据丢失了吗?我看到头文件确实为这些变量定义了字符串大小,但我不清楚当我使用ctypes定义变量时,如何解释这个字符串大小。你错误地声明了它,ctypes会盲目地使用错误的声明。J.F.塞巴斯蒂安给出了更准确的答案。谢谢J.F.--这非常有帮助
"""
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