我试图将Cython类嵌入C++类。鉴于项目的限制,无法为此C++类创建Cython包装器。而且由于Cython类中方法的数量众多以及Cython类的长继承性,因此从类中完全删除该方法并不是一种有吸引力的解决方案。对我来说,有必要创建一个Cython类实例并从C++调用其方法。但是,我似乎无法使其不成为段错误。这是问题的示例:
<<>>
from math import sin
cdef public class Foo[object Foo, type fooType]:
cdef double a,b
def __cinit__(self, double a, double b):
self.a = a
self.b = b
cdef double bar(self, double c):
return sin(self.a*c)
cdef api double foobar(Foo foo, double d):
return foo.bar(d)
<<>>
#include "fooClass_api.h"
#include <iostream>
int main(){
Py_Initialize();
import_fooClass();
Foo foo;
foo.a = 1.0;
foo.b = 10.0;
std::cout << foobar(&foo,5.0) << "\n";
Py_Finalize();
}
<<>>
from distutils.core import setup
from Cython.Build import cythonize
setup ( ext_modules = cythonize ("cyClass.pyx"))
我用
python setup.py build_ext --inplace
构建并用g++编译。通过测试,我知道Py_Initialize()
和import_fooClass
正在成功。而且我知道我在foo.a
内打印foo.b
和foobar()
的值,但是一旦我使用Foo
内的foobar()
对象进行调用,程序就会出现段错误。甚至对foo.__dict__
中的foo.callable()
或foobar()
的调用也会导致segfault。更改public
或api
关键字没有效果,也没有在__init__
和__cinit__
之间切换。如果有人知道如何解决此问题,我将不胜感激。我怀疑这与指针或滥用Python C API有关。非常感谢! 最佳答案
我设法解决了这个问题。根据David W所说的(感谢David!),我创建了另一个cdef api
类作为构造函数的包装器cdef api Foo buildFoo (double a, double b):
这将返回Foo*
指针,这是.pyx文件中foobar(Foo foo, double d)
所需的指针。生成的文件如下所示:
<<>>
from math import sin
cdef public class Foo[object Foo, type fooType]:
cdef double a,b
def __cinit__(self, double a, double b):
self.a = a
self.b = b
cdef double bar(self, double c):
return sin(self.a*c)
cdef api Foo buildFoo(double a, double b):
return Foo(a,b)
cdef api double foobar(Foo foo, double d):
return foo.bar(d)
<<>>
#include "fooClass_api.h"
#include <iostream>
int main(){
Py_Initialize();
import_fooClass();
Foo *foo = buildFoo(10.0,5.0);
std::cout << foobar(foo,5.0) << "\n";
Py_Finalize();
}
使用相同的
setup.py
脚本。运行此结果,将
-0.262375
打印到stdout,这是正确的结果。我希望在此代码中使用更复杂的版本来替换对boost::python的一些调用,以提高性能。