我的大部分库都是用 Cython 在“正常”C 模式下编写的。到目前为止,我很少需要任何 C++ 功能,但总是假设(有时确实如此!)如果我愿意,我可以将一个模块切换到 C++ 模式。
所以我有大约 10 个 C 模式模块和 1 个 C++ 模式模块。
现在的问题是 Cython 如何seems处理复数定义。在 C 模式下,它假设我认为 C 复数,而在 C++ 模式下,它假设我认为 C++ 复数。我读过它们现在可能是相同的,但无论如何 Cython 抱怨它们不是:
openChargeState/utility/cheb.cpp:2895:35: error: cannot convert ‘__pyx_t_double_complex {aka std::complex<double>}’ to ‘__complex__ double’ for argument ‘1’ to ‘double cabs(__complex__ double)’
__pyx_t_5 = ((cabs(__pyx_v_num) == INFINITY) != 0);
在这种情况下,我尝试使用 C 模式模块中定义的 cab,并从 C++ 模式模块中调用它。
我知道有一些明显的解决方法(现在我只是不使用 C++ 模式;我想使用向量,而暂时使用较慢的 Python 列表)。
有没有办法告诉我的 C++ 模式模块使用 C 复数,或者告诉它它们是相同的?如果我在 C++ 模式模块中找不到 ctypedef C 复数的工作方法...或者还有其他解决方案吗?
EDIT:DavidW 和 ead 的评论提出了一些合理的事情。首先是最小工作示例。
setup.py
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
from Cython.Build import cythonize
extra_compile_args=['-O3']
compdir = {'language_level' : '3'}
extensions = cythonize([
Extension("cmod", ["cmod.pyx"]),
Extension("cppmod", ["cppmod.pyx"], language='c++')
],
compiler_directives = compdir
)
setup(cmdclass = {'build_ext': build_ext},
ext_modules = extensions
)
import cppmod
cmod.pyx
cdef double complex c_complex_fun(double complex xx):
return xx**2
cmod.pxd
cdef double complex c_complex_fun(double complex xx)
cdef extern from "complex.h":
double cabs(double complex zz) nogil
cpmod.pyx
cimport cmod
cdef double complex cpp_complex_fun(double complex xx):
return cmod.c_complex_fun(xx)*abs(xx) # cmod.cabs(xx) doesn't work here
print(cpp_complex_fun(5.5))
然后只需使用 python3 setup.py build_ext --inplace 进行编译即可。
现在有趣的部分是(如代码中所写)只有“间接”导入的 c 函数有问题,就我而言cabs。所以建议只使用abs实际上确实有帮助,但我仍然不明白底层逻辑。我希望我不会在其他问题中遇到这个问题。我暂时留下这个问题。也许有人知道发生了什么事。