【发布时间】:2018-03-21 08:18:16
【问题描述】:
我的问题很简单,我有一个用 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我认为是由于 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/"]
)
]
)
【问题讨论】:
-
你是不是忘了给
static_method加上int参数? -
只是忘记从我复制的 cpp 文件中删除它抱歉,如果我弄乱了参数,它将无法编译。
-
我认为您需要在外部块中使用标题
cppClass.h? (可能还将其路径添加到include_dirs) -
您的设置看起来不错。你需要分析哪里出了问题。首先验证您的构建是否确实有效:将“-Wl,--no-undefined”添加到链接参数:现在链接器并不关心是否找到了所有符号,因此您只会在运行时看到缺失值。您还可以添加“-Wl,--verbose”以查看链接期间使用了哪些库。调用
readelf -d cy_wrapper.so| grep NEEDED看看mycustomlib是否真的被标记为需要。使用LD_DEBUG=libs,files,symbols python -c "import cy_wrapper"查看运行时出现的问题。 -
@ead 你说得对,
mycustomlib没有标记为需要,添加-Wl,--no-undefinedarg 显示了很多未定义的PySomeFunc和我的standalonefunc 和我的static的引用方法。我不知道静态的,我可以在 python 中调用它并查看 c++ 输出。 @chrisb 我想避免使用它,因为我正在使用一个我不应该拥有源代码的共享库。
标签: python c++ python-3.x cython wrapper