Cython:无法调用共享库的非静态方法

时间:2018-03-21 08:18:17

标签: python c++ python-3.x cython wrapper

我的问题非常简单,我有一个用CMake编译的共享库,我想为它包含的一个cpp类和一个独立的函数编写一个python包装器。

让我们说这个课程是独立的功能

// cppClass.cpp
void standalone() 
{ 
    printf("I am not alone\n"); 
}
int cppClass::not_static_method(int value)
{
    printf("I am not static\n");
    return value;
}
cppClass* cppClass::static_method()
{
    cppClass* c = new cppClass();
    if (!c) { return NULL; }
    return c;
}

// cppClass.h
#ifndef __CPPCLASS_H__
#define __CPPCLASS_H__
void standalone();
class cppClass
{
public:
    int not_static_method(int value);
    static cppClass* static_method();
};
#endif

所以我在我的.pxd文件中声明它并在我的.pyx文件中写了一个小包装类:

# .pxd
cdef extern:
    cdef cppclass cppClass:
        int not_static_method(int value)
        @staticmethod
        cppClass* static_method()
    cdef void standalone()
# .pyx
cdef class PyClass:
    cdef cppClass* c_clazz
    def __cinit__(self):
        self.c_clazz = cppClass.static_method()
    def NotStatic(self, value):
        standalone()
        return self.c_clazz.not_static_method(value)

问题是,编译后,我可以初始化一个PyClass对象,但是调用后一个对象的方法NotStatic会引发一个undefined symbol: standalone,当我评论对该函数的调用时,它引发segmentation fault,我认为这是由c_clazz对象内指针PyClass的初始化引起的。

我知道我无法指定定义的位置,因为它是一个extern库,我已经在setup.py文件中指定了它的名称,并在extra_link_args中指定了它的路径。

我在做什么(可能非常)错了?

编辑:共享库使用g++ -shared -fPIC -c cppClass.cpp -o libcppClass.so

进行编译

编辑2:添加了.h文件

编辑3:我没有提到为什么我要使用共享库,因为非静态方法在编译到共享库中的CUDA文件中使用了一些定义。

编辑4:我的设置文件

# setup.py
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext

setup(
    cmdclass = {"build_ext": build_ext},
    ext_modules = [
            Extension("cy_wrapper",
                      sources=["cy_wrapper.pyx"],
                      libraries=["mycustomlib"],
                      language="c++",
                      extra_compile_args=["-O3", "-Wall", "-std=c++11"],
                      extra_link_args=["-L/absolute/path/to/libmycustomlib.so/directory/"]
                      )
                  ]
)

1 个答案:

答案 0 :(得分:2)

检查Cython(cy_wrapper.cpp)生成的代码表明了这一点 函数standalone声明为

__PYX_EXTERN_C DL_IMPORT(void) standalone(void);

即。

extern "C" void standalone(void);

不是cppClass.h中定义的(C ++名称重整问题)。

cppClass在生成的文件中也有所不同

struct cppClass;
struct cppClass {
    virtual int not_static_method(int);
    static cppClass *static_method(void);
    virtual ~cppClass() { }
};

即。不是cppClass.h中定义的。定义应该匹配 或者像分段错误一样存在问题。

我建议在.pxd文件中包含头文件,即

cdef extern from "cppClass.h"