我试图在C ++类中嵌入一个Cython类。考虑到项目的约束,不可能为此C ++类创建Cython包装器。由于Cython类中的方法数量和Cython类的长继承性,完全从类中删除方法并不是一个有吸引力的解决方案。我有必要创建一个Cython类实例并从C ++调用它的方法。但是,我似乎无法使其成为段错误。以下是问题的一个示例:
<<<文件:fooClass.pyx>>>
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)
<<<文件:Foo.cpp>>>
#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();
}
&LT;&LT;&LT;文件:setup.py&gt;&gt;&gt;
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()
,也会导致其发生段错误。更改public
或api
个关键字已生效,也未在__init__
和__cinit__
之间切换。如果有人知道如何解决这个问题,我会非常感激。我怀疑它与指针或滥用Python C API有关。非常感谢!
答案 0 :(得分:1)
我设法解决了这个问题。基于David W所说的内容(感谢David!),我创建了另一个cdef api
类来充当构造函数的包装器,cdef api Foo buildFoo (double a, double b):
这将返回一个Foo*
指针,该指针需要.pyx文件中的foobar(Foo foo, double d)
。生成的文件如下所示:
&LT;&LT;&LT;文件:fooClass.pyx&gt;&gt;&gt;
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)
&LT;&LT;&LT;文件:Foo.cpp&gt;&gt;&gt;
#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的一些调用,以提高性能。
答案 1 :(得分:1)
在更复杂的设置中使用前面提到的技术并反复获取段错误后,这是我使用的替代方法。关键区别在于api
文件中的public
和pyx
关键字以及foo.cpp
中如何包含和使用该类。
&LT;&LT;&LT;文件:fooClass.pyx&gt;&gt;&gt;
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 public Foo buildFoo(double a, double b):
return Foo(a,b)
cdef public double foobar(Foo foo, double d):
return foo.bar(d)
&LT;&LT;&LT;文件:Foo.cpp&gt;&gt;&gt;
#include <Python.h>
#include "fooClass.h"
#include <iostream>
int main(){
Py_Initialize();
initfooClass();
Foo *foo = buildFoo(10.0,5.0);
std::cout << foobar(foo,5.0) << std::endl;
Py_Finalize();
}