我正在使用Cython为
Python编写一个高级界面的Python.
我有一个扩展类型A,它使用指向更复杂的C上下文结构c_context的指针来初始化库.指针保存在A.
A还有一个def函数,它又创建另一个扩展类型B,使用库函数调用初始化另一个C结构.这种结构对于在B中进行的后续库调用是必需的
B需要来自A的c_context指针,它由我在扩展类型py_context中包装,以便从B传递给__cinit__:
我有一个扩展类型A,它使用指向更复杂的C上下文结构c_context的指针来初始化库.指针保存在A.
A还有一个def函数,它又创建另一个扩展类型B,使用库函数调用初始化另一个C结构.这种结构对于在B中进行的后续库调用是必需的
B需要来自A的c_context指针,它由我在扩展类型py_context中包装,以便从B传递给__cinit__:
#lib.pxd (C library definitions) cdef extern from "lib.h": ctypedef struct c_context: pass #file py_context.pxd from lib cimport c_context cdef class py_context: cdef c_context *context cdef create(cls,c_context *context) cdef c_context* get(self) #file py_context.pyx def class py_context: @staticmethod cdef create(cls,c_context *c): cls = py_nfc_context() cls.context = c return cls cdef c_context* get(self): return self.context
用正确的C语言传递包装器完美.
现在我需要再次从py_context得到C结构,并保存在B中.我将cdef c_context get(self)添加到py_context.pxd / pyx.
从Bs __cinit__调用py_context.get()导致:AttributeError:py_context对象没有属性get.
解决方法
麻烦的是,Cython在编译时不知道py_context变量的数据类型.对cdef函数的调用在编译时解析,并且没有机制通过属性查找在运行时找出它(与普通的Python函数一样).
[注意,Cython中编写的def函数仍然被编译,并且可以指定数据类型,所以如果它们具有正确的信息,完全可以调用cdef函数.
你不会给出相应的代码(B类的构造函数),但这是一个非常简化的例子,希望能给你几种方法来解决它:
cdef class A: cdef f(self): return def f1(var): var.f() #f1(A()) # will fail at runtime with an attribute error
在f1中,var的类型是未知的,因此您不能调用cdef函数.
def f2(A var): var.f() f2(A()) # will work f2(1) # will fail,int can't be converted to A
在f2中,var的类型被限制为A,因此它可以愉快地调用与A相关联的cdef函数.如果你传递的东西不是A,那么你将在运行时得到一个TypeError.
def f3(var): cdef A another_reference_to_var = var # this does test that the types match another_reference_to_var.f() f3(A()) # will work f3(1) # will fail,int can't be converted to A
函数f3可以采用任何类型的变量.但是,当您将其分配给另一个被定义为A的an_reference_to_var时,它会检查该类型是否匹配(如果没有则引发运行时异常).由于在编译时已知an_reference_to_var为A,因此可以调用As cdef函数.
本质上,您需要指定__cinit__函数的相关输入类型.