Итак, я пишу Python API для библиотеки C ++, используя Cython.У меня есть три класса с почти идентичной функциональностью: A
, B
и C
.Эта разница заключается только в том, как один из их объектов построен на инициализации и некоторых константах.
Первоначально я записал их все как отдельные классы, а затем смог определить их через extern в моем коде Cython.Это компилируется и работает хорошо, но много повторяющегося кода, и мне бы очень хотелось, чтобы этот проект был более СУХИМ.
Поэтому я решил написать базовый класс для 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] * 'to' BaseClass [T] * 'Traceback (последний вызов был последним): файл "setup.py", строка 9, в настройке (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) File "/ 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
Кто-нибудь знает, как это сделать?Очевидно, моя замена шаблона отключена.Должен ли я придерживаться повторяющегося кода вместо этого?Есть ли другие умные решения?