Tutorial说.pyx
和.pxd
文件不应该具有相同的名称,除非.pyx
是.pxd
文件中定义的实现。
请注意,.pyx文件的名称必须与.cx文件的名称不同 带有来自C库的声明的cqueue.pxd文件,因为两者都没有 描述相同的代码。 .pyx文件旁边的.pxd文件具有相同的文件 name定义.pyx文件中代码的导出声明。作为 cqueue.pxd文件包含常规C库的声明 不能是与Cython关联的名称相同的.pyx文件 它
然而,即使.pxd
cdef extern
cpp声明与.pyx
代码无关,但只有当这两个文件的名称相同时,它才能正常运行。
py_test.pyx:
# distutils: language = c++
from py_test cimport Test
def f():
Test[double](2.) + 3.
zzz.pyx:
# distutils: language = c++
from py_test cimport Test
def f():
Test[double](2.) + 3.
py_test.pxd:
cdef extern from "cpp_test.h":
cdef cppclass Test[T]:
Test()
Test(T value)
T value
cdef Test[T] operator+[T](Test[T]&, T)
cpp_test.h:
template<typename T>
class Test {
public:
T value;
Test():value(0){}
Test(T value):value(value){}
~Test(){}
};
template<typename T>
Test<T> operator+(const Test<T>& x, T y) {
return Test<T>(x.value + y);
}
setup.py:
from distutils.core import setup
from Cython.Build import cythonize
setup(
name = "demo", # unused
# ext_modules = cythonize('py_test.pyx'), # ok
ext_modules = cythonize('zzz.pyx'), # Invalid operand types for '+' (Test[double]; double)
)
答案 0 :(得分:2)
教程说.pyx和.pxd文件不应该具有相同名称的原因是,如果找到具有相同名称的文件,.pyx文件将自动执行相当于from pxd_file_with_the_same_name cimport *
的文件。 / p>
因此,避免让不相关的文件具有相同名称的原因只是为了避免在某些内容得到cimport
的情况下出现令人困惑的行为。
这个具体案例与Cython如何导入非成员C ++运算符有关,坦白说这有点儿麻烦。请参阅this previous question。
非成员运算符只有在cimport
进入当前模块范围时才可用于Cython(即只导入相关类不会这样做)。不幸的是,我无法直接cimport
,但如果您将zzz.pyx
更改为
from py_test cimport *
然后*
设法cimport
运营商,它应该有效。由于py_test.pyx
隐式执行此操作,因此无需进一步更改即可正常工作。
(关于你previous question about complex的动机,我尝试弄乱这种想法并且无法立即让它发挥作用,但也许你会比我更幸运)
答案 1 :(得分:1)
另一种cimporting operator+
的方法是这样的:
zzz.pyx
# distutils: language = c++
from py_test cimport Test, add
def f():
add(Test[double](2.), 3.)
pytest.pxd:
cdef extern from "cpp_test.h":
cdef cppclass Test[T]:
Test()
Test(T value)
T value
cdef Test[T] add "operator+"[T](Test[T]&, T)
在某些情况下,它可能优于cimport *
,但它并不理想,因为它会改变运算符调用的语义。