Cython Class C++ 中的继承和嵌入
Cython Class Inheritance and embedding in C++
我需要将我的 Cython classes 嵌入到一些 C++ 代码中,但我无法使继承工作,并且在尝试访问基 class 的字段时不断出现分段错误。由于项目的限制,无法包装 C++ class 或从 Cython 代码中删除 classes。这是我的问题的一个提炼示例:
<<< 文件: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)
<<< 文件: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()
}
当我运行这个时,我收到以下信息:
<<< 标准输出 >>>
buildFoo(a,b)
Foo.__init__ START
foobar(Foo,d)
Segmentation fault
我知道这种在 C++ 中嵌入 Cython 的方法只适用于 Foo class,但是当我尝试从 FooSuper
扩展 Foo
时,FooSuper.__init__
永远不会被调用。我知道这个问题一定来自我的初始化方法,但我已经将两个 __init__
s 转换为 __cinit__
s 没有任何变化。显然,段错误来自 FooSuper
的字段,根本没有被初始化。我也尝试过在 FooSuper
class 中添加一个空心的 __cinit__(self, *args)
,没有任何变化。如果有人可以帮助我,我将不胜感激。谢谢。
因此,经过更多尝试后,我设法回答了我自己的问题。正如我所怀疑的那样,问题出在 super class 的初始化中。这是结果:
<<< 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()
}
编译和运行没有问题:
<<< 标准输出 >>>
buildFoo(a,b)
FooSuper.__cinit__()
Foo.__init__() START
FooSuper.__init__() START
FooSuper.__init__() END
Foo.__init__() END
foobar(Foo,c)
0.14112
我需要将我的 Cython classes 嵌入到一些 C++ 代码中,但我无法使继承工作,并且在尝试访问基 class 的字段时不断出现分段错误。由于项目的限制,无法包装 C++ class 或从 Cython 代码中删除 classes。这是我的问题的一个提炼示例:
<<< 文件: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)
<<< 文件: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()
}
当我运行这个时,我收到以下信息:
<<< 标准输出 >>>
buildFoo(a,b)
Foo.__init__ START
foobar(Foo,d)
Segmentation fault
我知道这种在 C++ 中嵌入 Cython 的方法只适用于 Foo class,但是当我尝试从 FooSuper
扩展 Foo
时,FooSuper.__init__
永远不会被调用。我知道这个问题一定来自我的初始化方法,但我已经将两个 __init__
s 转换为 __cinit__
s 没有任何变化。显然,段错误来自 FooSuper
的字段,根本没有被初始化。我也尝试过在 FooSuper
class 中添加一个空心的 __cinit__(self, *args)
,没有任何变化。如果有人可以帮助我,我将不胜感激。谢谢。
因此,经过更多尝试后,我设法回答了我自己的问题。正如我所怀疑的那样,问题出在 super class 的初始化中。这是结果:
<<< 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()
}
编译和运行没有问题:
<<< 标准输出 >>>
buildFoo(a,b)
FooSuper.__cinit__()
Foo.__init__() START
FooSuper.__init__() START
FooSuper.__init__() END
Foo.__init__() END
foobar(Foo,c)
0.14112