使用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
方法以连接"它们.
每个组件始终的input
和output
字段存储struct beam
的实例-一种仅存储double complex
字段和double
字段的数据类型./p>
目前,我正在使用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)]
有什么方法可以获取类型为struct vector**
的某个组件(例如mirror
)的output
字段的地址,并将其传递给例如某些函数input
参数?
此外,我认为有必要在python结构的_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]),...)
此外,我认为有必要在python结构的 fields 中创建与C结构中的字段相对应的所有字段-即是否可以从此描述符中省略某些字段?
否,您不能从结构定义中忽略字段,否则基础C结构的二进制布局将不正确.
I have a vector
struct in C with the following fields,
struct vector {
unsigned char* data;
unsigned long size;
unsigned long elemsize;
unsigned long capacity;
};
and there are a few functions which correspondingly act on vector
instances, such as:
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);
...
and so on (mimicking a c++ style std::vector
).
In other sections of my code base I have component structs, for example 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>*]
};
which, amongst others, has the following methods,
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);
where one passes the address of another components' output
field to these set_input
methods to "connect" them.
The input
and output
fields of every component always store instances of struct beam
- a data-type which simply stores a double complex
field and a double
field.
Currently I am in the process of building wrappers in Python (3.5) to call the various methods in an object-oriented to use later on for easier plotting and so forth; using ctypes to build a shared library of the C code.
The following are the wrappers that I have so far,
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)]
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?
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?
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?
To access the output component of a Mirror given your structures:
>>> m = Mirror()
>>> m.output[0]
<__main__.LP_Vector object at 0x00000199607CA0C8>
To pass it to a function by reference:
>>> 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?
No, you cannot omit fields from your structure definition, or the binary layout of the underlying C structure won't be correct.
这篇关于使用ctypes从Python获取C中的自定义数据类型的地址的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!