共享库符号名称

shared library symbol names

本文关键字:符号 共享      更新时间:2023-10-16

我希望能够使用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",并确保遵守相关限制-请参阅此处了解其解释。