在Cython中包装模板化基类的子类

时间:2018-12-31 18:10:40

标签: c++ templates cython template-specialization base-class

因此,我正在使用Cython为C ++库编写Python API。我有三个具有几乎相同功能的类:ABC。这种区别只是它们的对象之一是如何基于初始化和某些常量构建的。

最初,我将它们全部写为单独的类,然后可以在我的cython代码中通过extern定义它们。这样可以编译并运行良好,但是有很多重复的代码,我真的希望这个项目更加DRY。

因此,我决定为ABC写一个实现了大部分功能的基类。但是,我需要为该基类建立模板,这在我尝试在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

有人知道该怎么做吗?显然,我的模板替换已关闭。我应该坚持使用重复代码吗?还有其他聪明的解决方案吗?

1 个答案:

答案 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__中)