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
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
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) 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) a pointer to a serial number (I can make this up: an arbitrary string)
3) A pointer to PicamCameraID
, a variable type defined within the DLL, based on the struct
type
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))
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.
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
returns "2" which is great that's what I specified
myid.computer_interface
returns "1" which is fine
BUT the problem is myid.serial_number
returns
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:
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)
Kind regards
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;
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)]
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
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With