1

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 と 2 つの子クラス Cat と Dog があります。子クラスは Mammal クラスのメソッド run() を使用しますが、独自の eat() メソッドを定義します。

私にとって意味のあるレイアウトは、基本クラスのファイルを持っていることです:

# c_mammal.pxd

def extern from 'CMammal.h':
    cdef cppclass CMammal:
        void run()

子クラスの定義、例えば Cat:

# 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 ファイルにもまったく同じ Mammal コードを書かなければならないということです。これは機能しますが、意図したソリューションにはなりません。

4

0 に答える 0