我正在尝试使用CFFI在一些现有的C code周围构建一个python接口。像往常一样,为提高性能而对C代码进行了修剪,但到处都是大量的宏和typedef。
我正在复制以下结构的ATM
#define DIM 3
typedef double REAL;
struct Object_structure {
int numpoints;
REAL (* vertices)[DIM];
int * rings;
};
typedef struct Object_structure * Object;
我尝试调用的函数需要一个
Object
类型的参数。REAL gjk_distance(
Object obj1, REAL (* tr1)[DIM+1],
Object obj2, REAL (* tr2)[DIM+1],
REAL wpt1[DIM], REAL wpt2[DIM],
struct simplex_point * simplex, int use_seed
);
我已经编写了下面的python类来表示这样的对象/结构,但是我很难将其转换为预期的cdata对象。 (目前,我只是考虑一个UnitCube,但最终我将要归纳一下。)
class Box:
def __init__(self, pos):
self._weakkeydict = weakref.WeakKeyDictionary()
self.numpoints = 8
self.rings = [
8, 12, 16, 20, 24, 28, 32, 36,
3, 1, 4, -1,
0, 2, 5, -1,
1, 3, 6, -1,
2, 0, 7, -1,
7, 5, 0, -1,
4, 6, 1, -1,
5, 7, 2, -1,
6, 4, 3, -1]
x, y, z = pos
self.vertices = [
[x+0, y+0, z+0],
[x+1, y+0, z+0],
[x+1, y+1, z+0],
[x+0, y+1, z+0],
[x+0, y+0, z+1],
[x+1, y+0, z+1],
[x+1, y+1, z+1],
[x+0, y+1, z+1],
]
@property
def cdata(self):
self._weakkeydict.clear()
#ptr_numpoints = ffi.new("int", self.numpoints)
ptr_rings = ffi.new("int[]", self.rings)
vertices = [ffi.new("REAL[3]", v) for v in self.vertices]
ptr_vertices = ffi.new("REAL *[3]", vertices )
ptr_obj = ffi.new("Object", {
'numpoints': self.numpoints,
'rings': ptr_rings,
'vertices': ptr_vertices})
self._weakkeydict[ptr_obj] = (ptr_rings, ptr_vertices, vertices)
return ptr_obj
有了以上内容,我在调用时在
IndexError: too many initializers for 'double *[3]' (got 8)
行中得到了ptr_vertices = ffi.new("REAL *[3]", vertices )
:box1 = Box((0,0,0))
box2 = Box((10,0,0))
d = lib.gjk_distance(
[box1.cdata], ffi.NULL,
[box2.cdata], ffi.NULL,
ffi.NULL, ffi.NULL,
ffi.NULL, 0 )
在我看来,尺寸似乎已经改变了。因为它应该是一个包含3个元素项的8元素数组。
我希望有人可以在这里指出正确的方向。
最佳答案
如果要创建单个项目,请使用ffi.new('REAL(*)[3]', [1, 2, 3])
。 *
周围的括号很重要。
在C语言中,类型REAL(*)[3]
表示指向REAL数组(大小= 3)的指针,而类型REAL*[3]
表示指向real数组的指针(大小= 3)。有关详细信息,请参见C pointer to array/array of pointers disambiguation。
现在,您将创建项目数组CFCF expects an array type代替。可以比较为:
ffi.new('int*', 1) # ok
ffi.new('int[]', 1) # wrong
ffi.new('int*', [1, 2, 3]) # wrong
ffi.new('int[]', [1, 2, 3]) # ok
ffi.new('REAL(*)[3]', [0.1, 0.2, 0.3]) # ok
ffi.new('REAL[][3]', [0.1, 0.2, 0.3]) # wrong
ffi.new('REAL(*)[3]', [[0.1, 0.2, 0.3], [0.4, 0.5, 0.6]]) # wrong
ffi.new('REAL[][3]', [[0.1, 0.2, 0.3], [0.4, 0.5, 0.6]]) # ok
关于python - 在CFFI中创建类型为“REAL(*顶点)[DIM]”的cdata,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39937895/