Cython: не удается вызвать нестатические методы общей библиотеки
Моя задача довольно проста, у меня есть общая библиотека, скомпилированная с CMake, и я хочу написать оболочку python для одного класса cpp, который он содержит, и отдельную функцию.
Предположим, что класс является этим с автономной функцией
// cppClass.cpp
void standalone()
{
printf("I am not alonen");
}
int cppClass::not_static_method(int value)
{
printf("I am not staticn");
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
.
setup.py
, а также ее путь как extra_link_args
.
Что я делаю (возможно, крайне) неправильно?
Edit: общая библиотека компилируется с помощью g++ -shared -fPIC -c cppClass.cpp -o libcppClass.so
Правка 2: добавлено .h
файл
Edit 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 ответ:
Проверка кода, сгенерированного 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"