Python和Ctypes访问带有嵌套结构的C 类
python and ctypes accessing c++ classes with nested structures
我有一个共享库和两个标头文件。我能够通过使用swig
创建绑定来使用库。但是,swig
版本非常慢,我没有设法包括对numpy
数组的支持。我现在正在尝试使用ctypes
从Python调用库的功能。
第一个标头包含一个extern "C"
块,该块通过宏来导出3个函数(我无法使用(。标题的简化版本看起来像这样:
...
class Foo;
typedef Foo* FOO_HANDLE;
#if !defined(__cplusplus)
# error "C++ Compiler only"
#endif
extern "C"
{
APIPROTOTYPE_EXT( MakeAlgo, FOO_HANDLE, (void) );
APIPROTOTYPE_EXT( DestroyAlgo, void, ( FOO_HANDLE ) );
APIPROTOTYPE_EXT( AlgoProcess, void, ( FOO_HANDLE, StructOne *, StructTwo *) );
}
通常,第一个函数MakeAlgo
返回指向Foo
类的实例,第二个功能DestroyAlgo
破坏了实例,第三个功能AlgoProcess
将两个结构作为输入作为输入,并将其一些值定为就位。<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
第二个标头包含StructOne
和StructTwo
的定义以及一些常数。StructTwo
包含几个嵌套结构。
在Python中,我使用ctypes.Structure
重写了第二个标头中包含的所有结构。我不在此处发布所有代码,但这是我定义嵌套结构的示例:
class StructTwo(Structure):
_fields_ = [("foo", StructFoo),
("dummy8", c_short)]
class StructFoo(Structure):
_fields_ = [("bar", c_uint),
("reserv1", c_uint),
("reserv2", c_uint)]
然后我的Python代码看起来像这样(假设结构在structures.py
文件中(:
from ctypes import *
from structures import StructOne, StructTwo
libfoo = ct.cdll.LoadLibrary(path/to/so/library)
makeAlgo = libfoo.MakeAlgo
makeAlgo.restype = c_void_p
makeAlgo.argtypes = []
destroyAlgo = libfoo.DestroyAlgo
destroyAlgo.restype = None
destroyAlgo.argtypes = [c_void_p]
submit = libfoo.AlgoProcess
submit.restype = None
submit.argtypes = [c_void_p, POINTER(StructOne), POINTER(StructTwo)]
handle = makeAlgo()
one = bar.StructOne()
two = bar.StructTwo()
submit(handle, byref(one), byref(two))
print(two.foo.bar) # unsigned int, should output 1, got 196611000 instead
destroyAlgo(handle)
创建指向Foo
类的指针并提交输入后,我检查了其中一个结构中的一些值,并且与预期结果不符。例如,我知道其中一个字段仅由图书馆设置为0或1,但是我得到了一些奇怪的结果,例如196611000。
有人知道什么问题(也许有人遇到了类似的问题(吗?可以是我定义结构的方式吗?或者也许是指向C 类的指针,该类别未正确处理?
编辑
我设法解决了初始问题。看来我定义结构的方式不正确。代替上述代码,应通过参考传递嵌套结构:
class StructTwo(Structure):
_fields_ = [("foo", POINTER(StructFoo)),
("dummy8", c_short)]
class StructFoo(Structure):
_fields_ = [("bar", c_uint),
("reserv1", c_uint),
("reserv2", c_uint)]
# Then to initialize the nested structure
foo = StructFoo()
two = StructTwo(pointer(foo)) # has to be pointer() not byref()
但是,要访问StructFoo
的字段,我必须做:
print(two.foo.contents.bar)
在实际代码中,我可能具有多达4个嵌套级别。是否有一种更优雅的方式来访问他们的领域:
two.foo.contents.baz.contents.qux.contents.field_value
我的编辑不正确。
问题在于,某些结构是比特场结构,指定了每个字段的宽度:
class StructTwo(Structure):
_fields_ = [("foo", StructFoo),
("dummy8", c_short)]
class StructFoo(Structure):
_fields_ = [("bar", c_uint, 1),
("reserv1", c_uint, 8),
("reserv2", c_uint, 16)]
ctypes中的位野外结构。
- 在nlohmann json中,如何将嵌套对象的数组转换为嵌套结构的向量
- 如何使用boost::具有嵌套结构和最小代码更改的序列化
- 用C#中的并集模拟C++嵌套结构
- 如何在 C++11 中查找和更新向量中的一个嵌套结构
- Lambda 捕获、初始值设定项和嵌套结构
- 给定一个C++嵌套的私有结构类型,是否有从文件范围静态函数访问它的策略
- 使用g++静态初始化带有命名标签的嵌套C++结构
- 重载嵌套结构/类的流插入运算符
- C++将结构传递给函数以访问嵌套结构
- C++ 在外部使用嵌套结构实现类函数
- 嵌套结构,从由空行分隔的文件中读取数据
- 在 glsl opengl 中将嵌套结构数组作为统一传递
- 如何创建结构的结构结构,等等嵌套多个结构?
- 嵌套在联合中的结构嵌套在 C 中的结构中
- 受保护的嵌套结构不能用作派生外部类中的返回类型?
- C++中的嵌套结构
- 嵌套的模板结构构造函数实现
- 使用嵌套结构初始化并集
- C++ 中的嵌套结构函数
- C++中匿名类型的嵌套结构