使用ctypes从Python中获取C中的自定义数据类型的地址
我在C中有一个带有以下字段的vector
结构,
struct vector { unsigned char* data; unsigned long size; unsigned long elemsize; unsigned long capacity; };
并且有一些函数相应地对vector
实例起作用,例如:
struct vector* vector_new(unsigned long elemsize); void vector_delete(struct vector* vec); void vector_push_back(struct vector* vec, void* value, unsigned long elemsize); void vector_reserve(struct vector* vec, unsigned long cap); ...
等等(模仿c ++风格的std::vector
)。
在我的代码库的其他部分,我有组件结构,例如mirror
:
struct mirror { double R; double T; // extra fields omitted - see mirror_wrapper.py below struct vector* input[2]; // [vector*, vector*] struct vector* output[2]; // [vector*, vector*] };
除其他外,其中有以下方法,
struct mirror* mirror_alloc(); int mirror_init(double R, double T, struct mirror* mrr); // ibn is the "initial-beam-number" void mirror_set_left_input(struct vector** input, unsigned long ibn, struct mirror* mrr); void mirror_set_right_input(struct vector** input, unsigned long ibn, struct mirror* mrr);
其中一个将另一个组件的output
字段的地址传递给这些set_input
方法以“连接”它们。
每个组件的input
和output
字段始终存储struct beam
实例 – 一种数据类型,它只存储double complex
字段和double
字段。
目前,我正在使用Python(3.5)构建包装器,以便在面向对象中调用各种方法,以便以后使用以便于绘图等等; 使用ctypes构建C代码的共享库。
以下是我到目前为止的包装,
vector_wrapper.py
from ctypes import cdll from ctypes import Structure from ctypes import c_ubyte from ctypes import c_ulong from ctypes import POINTER class Vector(structure): _fields_ = [ ("data", POINTER(c_ubyte)), ("size", c_ulong), ("elemsize", c_ulong), ("capacity", c_ulong)]
mirror_wrapper.py
from ctypes import cdll from ctypes import Structure from ctypes import byref from ctypes import c_double from ctypes import c_ubyte from ctypes import c_ulong from ctypes import c_bool from ctypes import POINTER from ctypes import pointer from vector_wrapper import Vector lib = cdll.LoadLibrary('./ctn_lib.so') class Mirror(Structure): _fields_ = [ ("R", c_double), ("T", c_double), ("pR", c_double), ("pT", c_double), ("tuning", c_double), ("mass", POINTER(c_double)), ("last_time", c_double), ("net_force", c_double), ("dfcoeff", c_double), ("phfcoeff", c_double*2), #phfcoeff is a double complex in c code ("rpfcoeff", c_double), ("input", POINTER(Vector)*2), ("output", POINTER(Vector)*2), ("has_left_input", c_bool), ("has_right_input", c_bool)]
有没有什么方法可以获得某个组件(比如mirror
)的output
字段的地址,它具有类型struct vector**
,并将其传递给,例如,某个函数Mirror.set_left_input
作为input
参数?
另外,我假设有必要在_fields_
结构的_fields_
中创建与C结构中的字段相对应的所有字段 – 即是否可以省略该描述符中的某些字段?
有没有什么方法可以获得某个组件(比如镜像)的输出字段的地址,它具有类型struct vector **,并将其传递给,例如,某个函数Mirror.set_left_input作为输入参数?
在给定结构的情况下访问Mirror的输出组件:
>>> m = Mirror() >>> m.output[0] <__main__.LP_Vector object at 0x00000199607CA0C8>
要通过引用将它传递给函数:
>>> mirror_set_left_input(byref(m.output[0]),...)
另外,我假设有必要在对应于C结构中的字段的python结构的字段中创建所有字段 – 即是否可以省略此描述符中的某些字段?
不,您不能省略结构定义中的字段,否则底层C结构的二进制布局将不正确。