对于TD2Hdl,这是一个奇怪的 typedef,但假设它是由于 C 代码返回分配的结构,下面演示了工作的 Python 代码。为了演示目的,我制作了一个虚拟 DLL 来分配和填充结构。
test.c
#include <stdlib.h>
#ifdef _WIN32
# define API __declspec(dllexport)
#else
# define API
#endif
typedef struct {
int dimSize;
int elt[1]; // 'x' wasn't legal, so assume size 1 and allocate more memory as needed.
} TD2;
typedef TD2 **TD2Hdl;
API void open_device(int* device_number) {
*device_number = 5;
}
API int get_sensor_values(int* device_number, unsigned long* timestamp, TD2Hdl values) {
int dimSize = 10; // could be any size
*device_number += 1; // just to prove the pointer content can change
*timestamp = 123;
*values = malloc(sizeof(TD2) + (dimSize - 1) * sizeof(int));
(*values)->dimSize = dimSize;
for(int i = 0; i < dimSize; ++i)
(*values)->elt[i] = i;
return 1;
}
test.py
from ctypes import *
class TD2(Structure):
_fields_ = (('dimSize', c_int),
('elt', c_int * 1)) # correct way to make an array
def __repr__(self): # make class be able to display itself
return f'TD2(dimSize={self.dimSize})'
dll = CDLL('./test')
# Match arguments and return value to C types. Note the **TD2 equivalent
dll.open_device.argtypes = POINTER(c_int),
dll.open_device.restype = None
dll.get_sensor_values.argtypes = POINTER(c_int), POINTER(c_ulong), POINTER(POINTER(TD2))
dll.get_sensor_values.restype = c_int
n = c_int()
dll.open_device(byref(n))
print(f'from open: n={n.value}')
ts = c_ulong()
td2 = POINTER(TD2)() # storage for the allocated pointer
ret = dll.get_sensor_values(byref(n), byref(ts), byref(td2))
print(f'from get: n={n.value} ts={ts.value} {td2.contents}')
# This is easier to do in C by indexing off the end of the array, but
# Python doesn't allow that, so to safely read the array in Python the
# address of the 'elt' can be cast to a pointer to an array of the
# correct size, then dereferenced and converted to a Python list
# to see the values.
data = list(cast(byref(td2.contents.elt), POINTER(c_int * td2.contents.dimSize)).contents)
print(data)
输出:
from open: n=5
from get: n=6 ts=123 TD2(dimSize=10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]