前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >C++导出C语言符号踩坑(一)

C++导出C语言符号踩坑(一)

原创
作者头像
liuzhen007
发布2025-02-23 11:32:21
发布2025-02-23 11:32:21
5700
代码可运行
举报
文章被收录于专栏:流媒体音视频
运行总次数:0
代码可运行

前言

理论上,对 C++ 工程进行 C 语言接口封装时,只需要在 C 头文件中声明混合编程即可,这样就可以避免 C++ 语言特殊的名称修饰行为。但是今天遇到了一个特例,所以想记录一下。

正文

直接说问题和现象,现在有一个 C++ 的方法 my_function,现在要将其导出为 C 语言接口的,头文件应该这样封装:

代码语言:c
代码运行次数:0
复制
#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++ 编译器修饰后的符号。

编译命令:

代码语言:bash
复制
g++ -shared -fPIC -o myclib.so mylib.cpp

但是,查看编译导出的动态库,发现符号还是修饰过的,查看导出符号可以使用下面的命令:

代码语言:bash
复制
nm -D myclib.so

如果是 windows 系统可以使用 dumpbin 命令:

代码语言:bash
复制
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 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 正文
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档