我正在尝试使用从Python用c ++编写的库。该库包含多个从基类继承的类,每个类都有自己的.cpp和.h文件。
在使用Cython访问那些类时(我只需要子类,但是使用基类中的方法),我只能通过在所有子类的pxd和pyx文件中重新定义基类来使其工作
如果我尝试为基类定义pxd(和pyx)文件,则会遇到问题,即我的基类的标头多次包含在Cython创建的.cpp文件中,并引发错误:重新定义'Class BaseClass'
这种设置的正确项目布局是什么?
我正在使用Ubuntu 16.04LTS,Python 3.5.2,Cython 0.29.7
由于MWE已经包含了很多文件,因此我仅在此处显示一些片段,但完整的代码在GitHub上: https://github.com/Heerpa/test_cython_cpp/commits/master
在MWE中,我有一个哺乳动物的基础班,还有两个猫和狗的孩子班。子类使用Mammal类的run()方法,但定义了自己的eat()方法。
对我来说有意义的布局是具有用于基类的文件:
# c_mammal.pxd
def extern from 'CMammal.h':
cdef cppclass CMammal:
void run()
以及子类的定义,例如猫:
# c_cat.pxd
from c_mammal cimport CMammal
cdef extern from 'CCat.h':
# cdef cppclass CMammal:
# void run()
cdef cppclass CCat(CMammal):
void eat()
现在,由于CCat.h包含CMammal.h以便从中继承,我得到了重新定义错误
building 'animals.dog' extension
x86_64-linux-gnu-gcc -pthread -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -g -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -fPIC -Isrc/animalcpplibrary/ -I/usr/include/python3.5m -c src/dog.cpp -o build/temp.linux-x86_64-3.5/src/dog.o
cc1plus: warning: command line option ‘-Wstrict-prototypes’ is valid for C/ObjC but not for C++
In file included from src/animalcpplibrary/CDog.h:2:0,
from src/dog.cpp:623:
src/animalcpplibrary/CMammal.h:3:7: error: redefinition of ‘class CMammal’
class CMammal {
^
In file included from src/dog.cpp:622:0:
src/animalcpplibrary/CMammal.h:3:7: error: previous definition of ‘class CMammal’
class CMammal {
^
error: command 'x86_64-linux-gnu-gcc' failed with exit status 1
相反,如果我使用CMammal包含在CCat中的事实,我可以这样做:
# c_cat.pxd
cdef extern from 'CCat.h':
cdef cppclass CMammal:
void run()
cdef cppclass CCat(CMammal):
void eat()
,并在cat.pyx中定义哺乳动物的功能:
# cat.pyx
# distutils: sources = [src/animalcpplibrary/CCat.cpp, src/animalcpplibrary/CMammal.cpp]
# distutils: language = c++
# distutils: include_dirs = src/animalcpplibrary/
# cython: language_level=3
cimport c_cat
cdef class PyMammal:
cdef c_cat.CMammal* thisptr
def run(self):
if self.thisptr:
self.thisptr.run()
cdef class PyCat(PyMammal):
def __cinit__(self):
if self.thisptr:
del self.thisptr
print('cinit Cat: allocating instance.')
self.thisptr = new c_cat.CCat()
def __dealloc__(self):
if self.thisptr:
print('dealloc Cat: deallocating instance')
del self.thisptr
def eat(self):
if self.thisptr:
(<c_cat.CCat*>self.thisptr).eat()
关键是,我必须在狗cython文件中编写完全相同的哺乳动物代码。这可行,但不能成为预期的解决方案。