理论上,对 C++ 工程进行 C 语言接口封装时,只需要在 C 头文件中声明混合编程即可,这样就可以避免 C++ 语言特殊的名称修饰行为。但是今天遇到了一个特例,所以想记录一下。
直接说问题和现象,现在有一个 C++ 的方法 my_function,现在要将其导出为 C 语言接口的,头文件应该这样封装:
#ifndef MYLIB_H
#define MYLIB_H
#ifdef __cplusplus
extern "C" {
#endif
void my_function();
#ifdef __cplusplus
}
#endif
#endif // MYLIB_H
头文件中使用 #ifdef __cplusplus 和 extern "C" 的目的是为了防止 C++ 的名称修饰,确保导出的符号是 C 语言风格的符号,而不是经过 C++ 编译器修饰后的符号。
编译命令:
g++ -shared -fPIC -o myclib.so mylib.cpp
但是,查看编译导出的动态库,发现符号还是修饰过的,查看导出符号可以使用下面的命令:
nm -D myclib.so
如果是 windows 系统可以使用 dumpbin 命令:
dumpbin /exports myclib.dll
可以确认的是 C++ 文件确实已经引入了带有 extern"C" 语句的头文件,而且,还有一个可以佐证的现象,就是定义多个方法时,有些方法符号是按照 C 语言规则导出的,有些则是 C++ 语言名称修饰后导出的。
另外,还有一个有意思的现象就是,越是复杂的方法出现 C++ 名称修饰的概率就越大。
后来,实践后发现,编译确实会根据方法参数的复杂度来决定是否使用 C++ 名称修饰,如果想强制使用 C 语言风格的导出符号,不仅需要在头文件中声明 #ifdef __cplusplus 和 extern "C" 语句,还需要在 C++ 文件中直接使用 extern "C" 语句包裹方法实现。
有些时候,以往的经验并不一定就是金科玉律,有时候也需要根据实际情况,灵活采取一些实验尝试。比如本次使用 extern "C" 语句的经历,C++ 文件实现部分,不需要判断 __cplusplus 宏定义,直接引用,避免可能因为没有宏定义导致的错误产生。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。