Cython:反教程行为

时间:2017-03-27 08:50:59

标签: python c++ templates operator-overloading cython

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) 
)

2 个答案:

答案 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 *,但它并不理想,因为它会改变运算符调用的语义。