因此,我正在使用Cython为C ++库编写Python API。我有三个具有几乎相同功能的类:A
,B
和C
。这种区别只是它们的对象之一是如何基于初始化和某些常量构建的。
最初,我将它们全部写为单独的类,然后可以在我的cython代码中通过extern定义它们。这样可以编译并运行良好,但是有很多重复的代码,我真的希望这个项目更加DRY。
因此,我决定为A
,B
和C
写一个实现了大部分功能的基类。但是,我需要为该基类建立模板,这在我尝试在Cython中定义所有内容时引起了一场噩梦。这是我正在谈论的一个玩具示例(忽略找到的分号等,如果找到它们的话)。这是我的“ classes.h”文件
int library_method_load(std::string file_name){
return std::string.length();
}
template <class T>
class BaseClass{
public:
T important_obj;
BaseClass(std::string file_name){ important_obj = library_method(file_name);};
virtual T library_method(std::string file_name) = 0;
// Important logicks...
~BaseClass(){};
}
class A : public BaseClass<int> {
A(std::string file_name): BaseClass<int>(file_name){};
int library_method(std::string file_name){ return library_method_load(file_name);};
~A(){};
}
当我尝试将其包装时,如果不向cython讲解基类,则会得到未定义的符号。如果我尝试定义基类,则模板会引起问题。后者可能是由于我不正确地继承模板化基类的语法。
这是我目前的尝试
#distutils: language = c++
from libcpp.string cimport string
cdef extern from "classes.h":
cppclass BaseClass[T]:
BaseClass(string file_name)
cdef extern from "classes.h":
cppclass A(BaseClass[int]):
A(string file_name)
cdef class PyBase:
cdef BaseClass* wrapped
cdef class PyA(PyBase):
def __cinit__(self, string file_name):
self.wrapped = <BaseClass[int]*> new A(file_name)
这样做会给我以下编译器错误:
编译Cython文件时出错: -------------------------------------------------- ---------- ...
cdef类PyA(PyBase):
def __cinit__(self, string file_name): self.wrapped = <BaseClass[int]*> new A(file_name)
^
wrapper.pyx:23:23:无法将类型'BaseClass [int] *'分配给 'BaseClass [T] *'追溯(最近一次通话):文件“ setup.py”, 第9行 setup(name =“ test”,version =“ 1.0.0”,ext_modules = cythonize([rk]))文件 “ /home/jacob/anaconda3/lib/python3.6/site-packages/Cython/Build/Dependencies.py”, 第1027行,在cythonize中 cythonize_one(* args)文件“ /home/jacob/anaconda3/lib/python3.6/site-packages/Cython/Build/Dependencies.py”, 1149行,在cythonize_one中 引发CompileError(None,pyx_file)Cython.Compiler.Errors.CompileError:wrapper.pyx
有人知道该怎么做吗?显然,我的模板替换已关闭。我应该坚持使用重复代码吗?还有其他聪明的解决方案吗?
答案 0 :(得分:0)
一种解决方案是删除PyBase
,因为在cdef BaseClass* wrapped
中缺少BaseClass
的模板参数,这使该行变得毫无意义。
例如:
cdef class PyA(PyBase):
cdef A* wrapped
def __cinit__(self, string file_name):
self.wrapped = new A(file_name)
(我不确定是否可以将C ++对象传递到__init__
和__cinit__
中)