2015-03-16 4 views
2

Если у меня есть абстрактный базовый класс и производный класс, который наследуется от него, но у меня есть другой класс, который принимает объект абстрактного базового класса в качестве аргумента, как мне его обернуть?Передача абстрактного класса C++ в качестве аргумента для Cython

class A { 
public: 
    A(int x, int y); 
    virtual int FooA(int x, int y) = 0; 
    virtual void FooB() = 0; 

} 

class B : public A{ 
    B(int x, int y, int z, int w); 
    int FooA(int x, int y); 
    void FooB(); 
    void FooC(int z, int w); 
} 

class C { 
public: 
    C(A* ptr, int p); 

} 

Как я могу обернуть это в целом? Я знаю, что я не должен обертывать абстрактный класс A, но у меня возникают трудности с упаковкой C, так как у меня нет объекта python для A

EDIT: На самом деле мне удалось обернуть класс, но я все еще получаю ошибки, которые Я проиллюстрирую далее.

source.pyx

cdef extern from "A.h" 
    cdef cppclass A: 
     A(int x, int y) 
     int FooA(int x, int y) 
     void FooB() 

cdef extern from "B.h" 
    cdef cppclass B(A): 
     B(int x, int y, int z, int w) 
     int FooA(int x, int y) 
     void FooB() 
     void FooC(int z, int w) 

cdef extern from "C.h" 
    cdef cppclass C: 
     C(A* ptr, int p) 

cdef class pyA: 
    cdef A* baseptr 
    def __cinit__(self, int x, int y): 
     if type(self) is A: 
      self.baseptr = new A(int x, int y) 

    def __dealloc__(self): 
     if type(self) is A: 
      del self.baseptr 

    def FooA(self, int x, int y): 
     pass 

    def FooB(self): 
     pass 

cdef class pyB(pyA): 
    def __cinit__(self, int x, int y, int z, int w): 
     if type(self) is pyB: 
     self.derivedptr = self.baseptr = new B(int x, int y, int z, int w) 
    def __dealloc__(self): 
     del self.derivedptr 

    def FooC(self, int z, int w): 
     self.derivedptr.FooC(int z, int w) 

cdef class pyC: 
    cdef C *thisptr 
    def __cinit__(self, pyA ptr, int p): 
     self.thisptr(<A *> ptr.thisptr, int p) 
    def __dealloc__(self): 
     del self.thisptr 

Это составитель, когда я испытывал ВПГ и передавая PYB в качестве первого аргумента, я получил:

TypeError: "Expected pyA, got pyB". 

не должны PYB быть в состоянии быть переданы в качестве первый аргумент, так как это подкласс pyA? Или я в отъезде?

+0

Вы можете, вероятно, избавиться от оставшейся ошибки путем удаление спецификатора типа 'PyA' из' PyC .__ cinit__'. [Также измените приведение на '', чтобы было возможно, что это может быть неправильный тип] – DavidW

ответ

3

Мой ответ опаздывает. Но для тех, кто может быть заинтересован, вот рабочий код.

хиджры

#ifndef A_H_ 
#define A_H_ 

class A { 
public: 
    virtual int FooA(int x, int y) = 0; 
    virtual void FooB() = 0; 
}; 

#endif /* A_H_ */ 

B.h

#ifndef B_H_ 
#define B_H_ 

#include "A.h" 

class B : public A{ 
public: 
    B(int x, int y, int z, int w); 
    int FooA(int x, int y); 
    void FooB(); 
    void FooC(int z, int w); 
}; 

#endif /* B_H_ */ 

C.h

#ifndef C_H_ 
#define C_H_ 

#include "A.h" 

class C { 
public: 
    C(A* ptr, int p); 
}; 

#endif /* C_H_ */ 

B.cpp

#include "B.h" 
#include <iostream> 

using namespace std; 

B::B(int x, int y, int z, int w) 
{ 
    cout << "B::B" << endl; 
    cout << x << " " << y << " " 
     << z << " " << w << endl; 
} 

int B::FooA(int x, int y) 
{ 
    cout << "B::FooA" << endl; 
    cout << x << " " << y << endl; 
    return 0; 
} 

void B::FooB() 
{ 
    cout << "B::FooB" << endl; 
} 

void B::FooC(int z, int w) 
{ 
    cout << "B::FooC" << endl; 
    cout << z << " " << w << endl; 
} 

C.cpp

#include "C.h" 
#include <iostream> 

using namespace std; 

C::C(A* ptr, int p) 
{ 
    cout << "C::C" << endl; 
    cout << ptr->FooA(0,1) << endl; 
    ptr->FooB(); 
} 

source.pyx

# distutils: language = c++ 
# distutils: sources = [B.cpp, C.cpp] 

cdef extern from "A.h": 
    cdef cppclass A: 
     A(int x, int y) except + 
     int FooA(int x, int y) 
     void FooB() 

cdef extern from "B.h": 
    cdef cppclass B(A): 
     B(int x, int y, int z, int w) except + 
     int FooA(int x, int y) 
     void FooB() 
     void FooC(int z, int w) 

cdef extern from "C.h": 
    cdef cppclass C: 
     C(A *ptr, int p) except + 

cdef class pyA: 
    cdef A *baseptr 
    def __cinit__(self): 
     pass 

    def FooA(self, int x, int y): 
     pass 

    def FooB(self): 
     pass 

cdef class pyB(pyA): 
    cdef B *derivedptr 
    def __cinit__(self, int x, int y, int z, int w): 
    self.derivedptr = new B(x, y, z, w) 
    self.baseptr = self.derivedptr 

    def __dealloc__(self): 
     del self.derivedptr 

    def FooC(self, int z, int w): 
     self.derivedptr.FooC(z, w) 

cdef class pyC: 
    cdef C *thisptr 
    def __cinit__(self, pyA ptr, int p): 
     self.thisptr = new C(ptr.baseptr, p) 

    def __dealloc__(self): 
     del self.thisptr 

setup.py

from distutils.core import setup 
from Cython.Build import cythonize 

setup(
    name = 'testapp', 
    ext_modules = cythonize('*.pyx'), 
) 

Наконец, скомпилировать

$python setup.py build_ext --inplace 
Смежные вопросы