2016-04-11 23 views
0

Ich muss meine Cython-Klassen in einigen C++ - Code einbetten, und ich kann die Vererbung nicht funktionieren und Segmentierungsfehler beim Zugriff auf Felder der Basisklasse erhalten. Aufgrund der Einschränkungen des Projekts ist es nicht möglich, die C++ - Klasse zu umbrechen oder die Klassen aus dem Cython-Code zu entfernen. Hier ist ein destilliertes Beispiel für mein Problem:Cython-Klasse Vererbung und Einbettung in C++

< < < Datei: fooClass.pyx >>>

from math import sin 

cdef public class FooSuper[object FooSuper, type FooSuperType]: 
    def __init__ (self, a): 
     print "FooSuper.__init__ START" 
     self.a = a 
     print "FooSuper.__init__ END" 

cdef public class Foo(FooSuper)[object Foo, type FooType]: 
    def __init (self, a, b): 
     print "Foo.__init__ START" 
     FooSuper.__init__(self, a) 
     self.b = b 
     print "Foo.__init__ END" 

    cdef double bar (self, double c): 
     return sin(self.a * c) 

cdef public Foo buildFoo (double a, double b): 
    print "buildFoo(a,b) START" 
    return Foo(a,b) 

cdef public double foobar (Foo foo, double c): 
    print "foobar(Foo,c) START" 
    return foo.bar(d) 

< < < Datei: foo.cc >>>

#include <Python.h> 
#include "fooClass.h" 
#include <iostream> 

int main(){ 
    Py_Initialize(); 
    initfooClass(); 
    Foo *foo = buildFoo(1.0, 2.0); 
    std::cout << foobar(foo, 3.0) << std::endl; 
    Py_Finalize() 
} 

Wenn Ich laufe das, ich bekomme folgendes:

< < < std out >>>

buildFoo(a,b) 
Foo.__init__ START 
foobar(Foo,d) 
Segmentation fault 

Ich weiß, dass dieser Ansatz Cython in C++ Einbettung nur mit der Foo-Klasse funktioniert, aber wenn ich versuche, Foo von FooSuper zu erweitern, die FooSuper.__init__ nie aufgerufen. Ich weiß, dass dieses Problem von meiner Methode der Initialisierung kommen muss, aber ich habe beide __init__ s zu __cinit__ s ohne Änderung umgewandelt. Der Segfault kommt eindeutig aus den Feldern FooSuper, die überhaupt nicht initialisiert werden. Ich habe auch versucht, eine hohle __cinit__(self, *args) zu der FooSuper Klasse ohne Änderung hinzuzufügen. Wenn mir jemand helfen kann, wäre ich sehr dankbar. Vielen Dank.

Antwort

0

So nach einigen weiteren Versuchen habe ich es geschafft, meine eigene Frage zu beantworten. Das Problem war, wie ich vermutete, die Initialisierung der Superklasse. Hier ist das Ergebnis:

< < < fooClass.pyx >>>

from math import sin 

cdef public class FooSuper[object FooSuper, type FooSuperType]: 

    cdef double a 

    #This is needed to initialize the underlying C struct of the super class 
    cdef __cinit__(self, *argv): 
     print "FooSuper.__cinit___()" 

    def __init__(self, a): 
     print "FooSuper.__init__() START" 
     self.a = a 
     print "FooSuper.__init__() END" 

cdef public class Foo(FooSuper) [object Foo, type FooType]: 
    cdef double b 

    def __init__(self, a, b): 
     print "Foo.__init__() START" 
     FooSuper.__init__(self, a) 
     print "Foo.__init__() END" 

    cdef double bar (self, double c): 
     return sin(self.a*c) 

cdef public Foo buildFoo (double a, double b): 
    print "buildFoo(a,b)" 
    return Foo(a,b) 

cdef public double foobar(Foo foo, double c): 
    print "foobar(Foo, c)" 
    return foo.foobar(c) 

< < < foo.cc >>>

#include <Python.h> 
#include "fooClass.h" 
#include <iostream> 

int main(){ 
    Py_Initialize(); 
    initfooClass(); 
    Foo *foo = buildFoo(1.0, 2.0); 
    std::cout << foobar(foo, 3.0) << std::endl; 
    Py_Finalize() 
} 

Dies kompiliert und läuft ohne Probleme ergeben:

< < < std out >>>

buildFoo(a,b) 
FooSuper.__cinit__() 
Foo.__init__() START 
FooSuper.__init__() START 
FooSuper.__init__() END 
Foo.__init__() END 
foobar(Foo,c) 
0.14112