我们提供了Cython代码:
cdef extern from "C_File_A.h":
cdef struct C_Obj_A:
pass
cdef extern from "C_File_B.h":
cdef struct C_Obj_B:
pass
cdef class pC_Obj_A:
cdef const C_Obj_A * _c_self
cdef class pC_Obj_B:
cdef const C_Obj_B * _c_self
cdef class pC_Obj_C:
cdef const C_Obj_A * _c_a
cdef const C_Obj_B * _c_b
cdef class Obj_A_Wrap(pC_Obj_A):
def __init__(self, pC_Obj_C obj_c):
self._c_self = obj_c._c_a
cdef class Obj_B_Wrap(pC_Obj_B):
def __init__(self, pC_Obj_C obj_c):
self._c_self = obj_c._c_b
cdef class Stack:
cdef public pC_Obj_A obj_a
cdef public pC_Obj_B obj_b
def __init__(self, pC_Obj_C obj_c):
# Working
self.obj_a = Obj_A_Wrap(obj_c)
self.obj_b = Obj_B_Wrap(obj_c)
# Working
self.obj_a._c_self = obj_c._c_a
self.obj_b = Obj_B_Wrap(obj_c)
# Working
self.obj_a = Obj_A_Wrap(obj_c)
self.obj_b._c_self = obj_c._c_b
# Not working
self.obj_a._c_self = obj_c._c_a
self.obj_b._c_self = obj_c._c_b
我需要一个Python对象Stack
,该对象具有可从Python访问的attrubuts,因此我将其添加到Stack类cdef public pC_Obj_A obj_a
和cdef public pC_Obj_B obj_b
中。这些对象是C结构指针的包装。
当我使用中间包装器(即Obj_A_Wrap
)初始化这些对象时,一切都很好。
当我直接初始化其中一个对象(即self.obj_a._c_self = obj_c._c_a
)时,一切都很好。
直接obj_a
和obj_b
都初始化时(代码的# Not Working
部分),我的C库出现奇怪的行为,包括C_File_A
和{{1} }和C结构定义。该行为类似于内存损坏,或覆盖了本不应该覆盖的部分内存。
我不知道为什么直接初始化会导致这种奇怪的行为。也许你知道吗?
答案 0 :(得分:1)
我找到了解决我问题的方法。当我尝试解决此问题时,我仅打印了给定对象的_c_self
属性,以检查是否正确分配了指针,并且确实如此,但是当我打印整个对象时,结果发现python对象为{{1} },而不是将适当的对象声明为属性。
None
解决方案是将print(self.obj_a, self.obj_b) # 66f000c0 66f000c0
print(f'{<int>self.obj_a._c_self:x} {<int>self.obj_b._c_self:x}') # None None
函数添加到cdef类:
Create
并像这样使用它:
cdef class pC_Obj_A:
cdef const C_Obj_A * _c_self
@staticmethod
cdef Create(C_Obj_A * ptr):
cdef pC_Obj_A result = pC_Obj_A()
result._c_self = ptr
return result
然后打印输出为:
cdef class Stack:
cdef public pC_Obj_A obj_a
cdef public pC_Obj_B obj_b
def __init__(self, pC_Obj_C obj_c):
self.obj_a = pC_Obj_A.Create(obj_c._c_a)
self.obj_b = pC_Obj_B.Create(obj_c._c_b)
一切都很好!