几天来我一直在尝试各种方法,但似乎缺少一些关键要素。我正在尝试创建一个C结构数组,并从Python字典中填充这些结构。我想在类定义或某些全局函数中捕获它,因为我将从代码中的多个位置使用它。
根据请求,我已将代码解构为最低版本,并将其全部放在一个文件中:
FOO_BOOL = 1
FOO_BYTE = 2
FOO_STRING = 3
cdef union Data:
bint flag
int byte
char *string
ctypedef struct bar_t:
char name[512]
int type
Data data
cdef class BarArray:
cdef bar_t *array;
cdef size_t nbars;
def __cinit__(self, number):
self.array = <bar_t*>malloc(number * sizeof(bar_t))
if not self.array:
raise MemoryError()
self.nbars = number
def load(self, keyvals:dict):
kvkeys = list(keyvals.keys())
if len(kvkeys) > <int>self.ninfo:
# this should never happen except in development
# so raise an error to let them know
raise IndexError()
n = 0
for key in kvkeys:
if keyvals[key][1] == 'bool':
self.array[n].type = FOO_BOOL
self.array[n].data.flag = keyvals[key][0]
elif keyvals[key][1] == 'byte':
self.array[n].type = FOO_BYTE
self.array[n].data.byte = keyvals[key][0]
elif keyvals[key][1] == 'string':
self.array[n].type = FOO_STRING
if isinstance(keyvals[key][0], str):
pykey = keyvals[key][0].encode('ascii')
else:
pykey = keyvals[key][0]
try:
self.array[n].data.string = strdup(pykey)
except:
raise ValueError("String value declared but non-string provided")
else:
raise TypeError("UNRECOGNIZED VALUE TYPE")
n += 1
@property
def array(self):
return self.array
@property
def nbars(self):
return self.nbars
cdef class FooClass():
cdef bar_t *array
cdef size_t sz
def __cinit__(self, sz):
self.bar = BarArray(sz)
def loadarray(self, keyvals:dict):
self.bar.load(keyvals)
self.array = <bar_t*>self.bar.array
while n < self.sz:
print("INFO [", n, "]: ", self.array[n].name, self.array[n].type)
n += 1
尝试编译时,出现以下错误:
warning: foobar.pyx:28:16: cdef variable 'array' declared after it is used
Error compiling Cython file:
------------------------------------------------------------
...
raise TypeError("UNRECOGNIZED VALUE TYPE")
n += 1
@property
def array(self):
return self.array
^
------------------------------------------------------------
foobar.pyx:67:19: Cannot convert 'bar_t *' to Python object
我读过一个地方,您必须将其强制转换为,但这也会产生错误。我最终设法找到了解决编译错误的方法,但是返回的数组包含垃圾。
任何建议将不胜感激。
答案 0 :(得分:0)
将指针发送回Python并没有实际意义(因此会看到错误)。我想您想做的就是定义Python访问器函数doReturn(newProds).when(enumOneSpy).getProdNames();
和__setitem__
:
__getitem__
请注意,您需要注意内存管理。因为您不能依靠指向继续存在的Python字符串中保存的数据的指针,所以需要为它们自己分配内存。这也意味着您需要确保在销毁类或替换数组元素时将其释放。我跳过了编写此代码的步骤,因为它很大程度上取决于您使用的C库。