共享库符号名称
shared library symbol names
我希望能够使用ctypes-python模块使用python中的C/C++函数。
我在.c
/.cpp
文件中有一个函数int doit()
。当我尝试加载共享库时:
Frr=CDLL("/path/FoCpy2/libFrr.so")
Frr.doit(c_int(5))
当使用.c
变体时,我发现它运行得非常好。当调用C++时,调用此函数的好方法是(发现使用nm libFrr.so
使用nm -gC libFrr.so
只生成普通的doit()
):
Frr._Z4doitv(c_int(5))
我在Stackeexchange上读到,从python调用C++没有标准的方法,而且存在"非标准名称篡改"问题。"Z4"是该问题的一部分吗?我想非标准的名称篡改会出现在更高级的语言功能中,比如类方法、模板,但也会出现在这样的基本函数中?在C++代码的简单情况下,是否可以强制使用简单的C函数名?
您可以使用extern "C"
使函数在外部世界中"看起来像"C函数(即禁用名称篡改)。是的,你是对的,名称篡改主要是为了C++所具有的更复杂的特性和函数类型,名称篡改方案从未标准化(二进制兼容性也从未标准化),因此不同编译器和不同版本之间的名称篡改方案各不相同(但大多数主流编译器现在已经习惯于永久性的,但编译器供应商之间仍然不同)。普通的旧自由函数也需要进行篡改,原因是C++支持重载(相同的函数名但具有不同的参数),因此编译器会将参数规范(例如类型)编码为被篡改的名称。当然,如果使用extern "C"
,则会丢失所有需要名称篡改的功能,因此,它或多或少只能归结为C函数。
您可以在每个函数的基础上使用extern "C"
,如下所示:
extern "C" int doit();
或者对于整个标题:
extern "C" {
// all the function declarations here ...
};
然而,特别是对于Python,我强烈建议您使用一个库,该库允许您构建反映C++类和函数的Python类和函数,这会让生活变得更轻松,并隐藏所有这些外部"C"业务。我建议使用Boost.Python,请参阅这个入门页面,它可以轻松地将函数和类导出到Python。我想其他人也会推荐SWIG,但我从来没有用过
调用c++库函数总是一团糟,实际上,即使您使用c++,也必须使用相同的编译器等来确保它正常工作。
唯一的通用解决方案是将您的c++函数定义为extern "C"
,并确保遵守相关限制-请参阅此处了解其解释。
- 为什么我的共享库中存在展开符号
- 仅在少数方法(静态或共享库)中解析的外部符号
- 共享对象、符号、C/C++ 库链接和加载
- 共享对象中的符号
- 如何防止 CMake 在构建时(而不是在安装时)为共享库创建符号链接?
- 使用共享库编译可执行文件时仅链接所需的符号
- 为什么 std:: 符号在共享库中被强制导出?
- 使用 C++ 标准库避免共享库中的符号冲突
- 隐藏共享库中的"_init"和"_fini"符号
- 共享对象中的符号名称与文件中.cpp函数不同
- C++:在共享对象中调用抽象基类构造函数/未定义的符号
- 共享库中使用"使用命名空间"定义的符号错误
- GCC 中使用 -O3 的共享库编译不会导出与 -O0 中那样多的符号
- Cython:共享对象中未定义的符号
- 不同的数学符号绑定与共享库与 dlopen 并直接链接到可执行文件 (Linux)
- 尝试与从 CUDA 对象构建的共享库链接时未定义的符号
- 在链接链接静态(GSOAP)库的共享库时,为什么会得到一个未定义的符号
- 共享库中非模板基的模板子类导致未定义的符号类型信息'class'链接错误
- 静态库将转换为共享的lib符号隐藏
- 在共享C++库中加载共享库时C++未定义的符号,该库本身由 Python 加载