Cython:无法调用共享库的非静态方法
Cython: unable to call non static methods of shared library
我的问题很简单,我有一个用 CMake 编译的共享库,我想为它包含的一个 cpp class 和一个独立函数编写一个 python 包装器。
假设 class 是独立函数
// 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
文件中写一个小包装器 class:
# .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
,我认为这是由于 PyClass
对象内部的指针 c_clazz
的初始化所致。
我知道我无法指定定义的位置,因为它是一个外部库,我已经在 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/"]
)
]
)
检查 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"
我的问题很简单,我有一个用 CMake 编译的共享库,我想为它包含的一个 cpp class 和一个独立函数编写一个 python 包装器。
假设 class 是独立函数
// 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
文件中写一个小包装器 class:
# .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
,我认为这是由于 PyClass
对象内部的指针 c_clazz
的初始化所致。
我知道我无法指定定义的位置,因为它是一个外部库,我已经在 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/"]
)
]
)
检查 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"