使用 ctypes 从 Python 获取 C 中自定义数据类型的地址
Obtaining address of custom data-type in C from Python using ctypes
我在 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<beam>*, vector<beam>*]
struct vector* output[2]; // [vector<beam>*, vector<beam>*]
};
除其他外,它具有以下方法,
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
方法 "connect" 它们。
每个组件的 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
参数?
此外,我假设有必要在 python 结构的 _fields_
中创建与 C 结构中的字段相对应的所有字段 - 即是否可以从中省略一些字段有没有描述符?
Is there any way in which I can get the address of an output field of some component (say a mirror), which has the type struct vector**, and pass this to, e.g., some function Mirror.set_left_input as the input parameter?
根据您的结构访问镜像的输出组件:
>>> m = Mirror()
>>> m.output[0]
<__main__.LP_Vector object at 0x00000199607CA0C8>
通过引用将其传递给函数:
>>> mirror_set_left_input(byref(m.output[0]),...)
Also, I assume it is necessary to create all fields in the fields of a python structure corresponding to the fields in the C structs - i.e. is it possible to omit some fields from this descriptor or not?
不,您不能从结构定义中省略字段,否则底层 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<beam>*, vector<beam>*]
struct vector* output[2]; // [vector<beam>*, vector<beam>*]
};
除其他外,它具有以下方法,
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
方法 "connect" 它们。
每个组件的 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
参数?
此外,我假设有必要在 python 结构的 _fields_
中创建与 C 结构中的字段相对应的所有字段 - 即是否可以从中省略一些字段有没有描述符?
Is there any way in which I can get the address of an output field of some component (say a mirror), which has the type struct vector**, and pass this to, e.g., some function Mirror.set_left_input as the input parameter?
根据您的结构访问镜像的输出组件:
>>> m = Mirror()
>>> m.output[0]
<__main__.LP_Vector object at 0x00000199607CA0C8>
通过引用将其传递给函数:
>>> mirror_set_left_input(byref(m.output[0]),...)
Also, I assume it is necessary to create all fields in the fields of a python structure corresponding to the fields in the C structs - i.e. is it possible to omit some fields from this descriptor or not?
不,您不能从结构定义中省略字段,否则底层 C 结构的二进制布局将不正确。