使用Python Ctypes将结构指针传递给DLL函数 [英] Using Python Ctypes to pass struct pointer to a DLL function

查看:98
本文介绍了使用Python Ctypes将结构指针传递给DLL函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用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_nameserial_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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆