Python ctypes:通过示例,正确地将c_void_p子类用于传递和返回自定义数据类型
我正在使用Python ctypes:通过示例,正确地将c_void_p子类用于传递和返回自定义数据类型,python,ctypes,Python,Ctypes,我正在使用ctypes,似乎不知道如何使用自定义数据类型。希望有一个Python接口,用于C++ Cys< /Cuff>类和C++ C++ > CyFiels类。p> 我当前的问题是使用C函数,名为 GETAYEnEntEngestAudioDIVE()/Cudio,下面定义了“代码>外”“C”{…/COD>。这个函数已被写入返回 Value*/Cudio>这是一个真正的 STD:vector < Cys*> ,指向C++的代码指针> Cys< /Cord>对象.< /P> 下面我的客户机代码显
ctypes
,似乎不知道如何使用自定义数据类型。希望有一个Python接口,用于C++<代码> Cys< /Cuff>类和C++ C++ > CyFiels类。p>
<>我当前的问题是使用C函数,名为CellComplex
方法elemen()
),在我看来它工作得很好。您会注意到我的elemen()
的Python实现将返回类型lib.elemen.restype
声明为(Python)的数组Cell
对象。这就是我得到的,>>print cmplx.elemen()
产生
[,,
,
,
]
但问题是:
现在,我想在列表中数组中的一个单元格
对象上调用我的C函数。例如,cmplx.elemen()[0][0]
是一个
,所以在我看来,我应该能够做到这一点:
cmplx.elemen()
我怀疑我没有正确地创建自定义Python类Cell
和CellComplex
。特别是在Python类Cell
中,方法dim(self):
我有一行lib.dim.argtypes=[Cell]
,这肯定是完全伪造的。还有,我有一个愚蠢的Python类c\u cellComplex
,它除了允许我自己指出某个特定的ctypes.c\u void\u p
应该指向什么之外,什么都不做。事实上,我声称我对这些Python类的定义完全是伪造的,我被欺骗到墨迹我在正确的轨道上,奇迹般地运行了它(直到我尝试在假定的Cell
实例上调用Cell
方法为止)
客户端代码:
p = [[0,1],[0,1]]
cmplx = cellComplex(p)
e = cmplx.elemen()
e[0][0].dim() # segfault
开始编辑提供了一个如何将c_void_p子类化的示例,并解决了一些其他概念问题-如果您有与我相同的问题,请从这里开始
segfault问题源于这样一个事实,即extern C{…
中定义的get_elementsAtSpecifiedDim()
将内存地址返回到std::vector
,这是一种无法在Python中解析的数据类型。在这种情况下,我可以获取向量中的指针并返回它们,如下所示:
extern "C" {
void * get_elementAtSpecifiedDimAndLoc(void *ptr, int dim, int nr) {
cellComplex<double>* cmplx = static_cast<cellComplex<double>* >(ptr);
cell<double>* c = cmplx->elemen()[dim][nr];
return c;
}
}
客户端代码现在可以工作。
结束编辑
这是一个伟大的愚蠢:
#cellComplex_python.py
lib=ctypes.cdll.LoadLibrary('./cellComplex_lib.so')
c类单元复合体(ctypes.c\u void\u p):
通过
类单元格(ctypes.c\u void\u p):
def dim(自身):
lib.dim.restype=ctypes.c_int
lib.dim.argtypes=[单元格]
self.dimension=lib.dim(self)
返回自我维度
类单元复合体(ctypes.c\u void\u p):
定义初始化(self,p):
自尺寸=透镜(p)
lib.new_cellComplex.restype=c_cellComplex
lib.new_cellComplex.argtypes=[(ctypes.c_double*2)*self.dimension,
ctypes.c\u size\u t]
e=[(ctypes.c_double*2)(p[i][0],p[i][1])表示范围内的i(自维)]
点=((ctypes.c_double*2)*自我维度)(*e)
self.cmplx=lib.new_单元复合体(点,self.dimension)
定义元素(自我):
lib.size\u elementsattspecifieddim.restype=ctypes.c\u int
lib.size_elementsattspecifieddim.argtypes=[c_cellComplex,
ctypes.c_int]
lib.get_elementsattspecifieddim.argtypes=[c_cellComplex,ctypes.c_int]
self.sizeAtDim=[]
self.elements=[]
对于范围内的i(自身尺寸+1):
self.sizeAtDim.append(lib.size\u elementsatsspecifieddim(self.cmplx,i))
lib.get_elementsattspecifieddim.restype=Cell*self.sizeAtDim[i]
self.elements.append(lib.get\u elementsatsspecifieddim(self.cmplx,i))
返回自我元素
C
code:
//cellComplex\u extern.cpp
#包括
#包括
外部“C”{
void*新单元复合体(双p[][2],尺寸尺寸){
std::vector点;
对于(size_t i=0;ielemen();
返回&e[dim];
}
int size_ELEMENTSATSPECIIEDDIM(无效*ptr,int dim){
cellComplex*cmplx=静态_铸造(ptr);
返回cmplx->elemen()[dim].size();
}
内部尺寸(无效*ptr){
单元*ref=静态_铸造(ptr);
返回ref->dim();
}
}
<代码> > CyVoIDIp P< <代码>,您可以定义类方法<代码> FasyPARAM< /COD>和实例属性<代码> -AASTyrasePrime< /Cord>。如果您只代理一个C++属性对象,则可以不需要任何选项,如“代码”>Obj< <代码>。可以直接与ctypes指针、数组和结构一起使用,这在总体设计中可能很方便
以下示例可能会有所帮助:
from ctypes import *
__all__ = ['CellComplex']
class Cell(c_void_p):
def __new__(cls, *args, **kwds):
raise TypeError("cannot create %r instances" % cls.__name__)
@property
def dimension(self):
return lib.dim(self)
class CellComplex(c_void_p):
def __init__(self, p):
pair = c_double * 2
point = (pair * len(p))(*(pair(*q[:2]) for q in p))
self.value = lib.new_cellComplex(point, len(p)).value
@property
def dimension(self):
"""Wrap a function that returns size_t."""
return lib.????????(self)
def get_elements(self):
el = []
for i in range(self.dimension):
size = lib.size_elementsAtSpecifiedDim(self, i)
cells = lib.get_elementsAtSpecifiedDim(self, i)
el.append(cells[:size])
return el
函数指针定义:
lib = CDLL('./cellComplex_lib.so')
lib.dim.restype = c_int
lib.dim.argtypes = [Cell]
lib.new_cellComplex.restype = CellComplex
lib.new_cellComplex.argtypes = [POINTER(c_double * 2), c_size_t]
lib.size_elementsAtSpecifiedDim.restype = c_int
lib.size_elementsAtSpecifiedDim.argtypes = [CellComplex, c_int]
lib.get_elementsAtSpecifiedDim.restype = POINTER(Cell)
lib.get_elementsAtSpecifiedDim.argtypes = [CellComplex, c_int]
我将函数指针定义从类方法定义中分离出来。无需每次调用方法时重新定义函数指针的restype
和argtypes
。如果函数返回大小可变的数组,最好将其设置为指针类型。可以将结果切片到列表或<代码>强制转换为数组类型
CellComplex
由浮点对的序列p
初始化,如[[0.1,0.2],[0.3,0.4],[0.5,0.6]
lib = CDLL('./cellComplex_lib.so')
lib.dim.restype = c_int
lib.dim.argtypes = [Cell]
lib.new_cellComplex.restype = CellComplex
lib.new_cellComplex.argtypes = [POINTER(c_double * 2), c_size_t]
lib.size_elementsAtSpecifiedDim.restype = c_int
lib.size_elementsAtSpecifiedDim.argtypes = [CellComplex, c_int]
lib.get_elementsAtSpecifiedDim.restype = POINTER(Cell)
lib.get_elementsAtSpecifiedDim.argtypes = [CellComplex, c_int]