C/C++ 混合编译 C++中的extern “C“
C/C++ 混合编译 C++中的extern “C”
gcc
编译*.c
和*.cpp
文件依据各自的文件类型各自编译为C
型目标文件和C++
类型目标文件g++
编译*.c\*.cpp
文件,都是编译为C++类型的目标文件使用
g++
时,不论是*.c
还是*.cpp
都将链接std c++
库。而gcc
是依据各自文件类型链接相应的std c
库或者是std c++
库
当一个程序有通过g++编译的C++目标模块与通过gcc编译的C目标模块时,链接会报错。案例如下:
test.c
int sum(int a,int b){return a + b;
}
main.cpp
#include <iostream>
using namespace std;
int sum(int a,int b);
int main(){int a = 10;int b = 20;cout << sum(a,b) << endl;
}
在终端中输入以下指令
xtark@xtark-vmpc:~/桌面/linux_study/section2$ gcc -c test.c
xtark@xtark-vmpc:~/桌面/linux_study/section2$ g++ -c main.cpp
xtark@xtark-vmpc:~/桌面/linux_study/section2$ g++ main.o test.o
main.o:在函数‘main’中:
main.cpp:(.text+0x21):对‘sum(int, int)’未定义的引用
collect2: error: ld returned 1 exit status
链接生成可执行文件的过程中报错显示找不到sum函数定义,这是为什么呢?通过汇编文件可以看出问题所在
在终端中输入以下指令:
xtark@xtark-vmpc:~/桌面/linux_study/section2$ gcc -S test.c
xtark@xtark-vmpc:~/桌面/linux_study/section2$ g++ -S main.cpp
test.s
中部分内容
.file "test.c".text.globl sum.type sum, @function
sum:
.LFB0:.cfi_startprocpushq %rbp
main.s
中部分内容
subq $16, %rspmovl $10, -8(%rbp)movl $20, -4(%rbp)movl -4(%rbp), %edxmovl -8(%rbp), %eaxmovl %edx, %esimovl %eax, %edicall _Z3sumii
可以看出,test.c
通过gcc
编译出的汇编文件中sum
函数名是sum
,而main.cpp
通过g++
编译出的汇编文件中sum
函数名则变成了_Z3sumii
。为什么会有这种差异呢?
这是因为C++支持多态性(这里是静态多态),也就是同名函数可以完成不同的功能,C++编译器通过函数参数区分具体调用的是哪一个函数。因此在编译的时候,C++编译器会将参数类型和函数名连接在一起,如main.s中的_Z3sumii
,ii
表示两个参数都是int
。于是在程序编译成为目标文件以后,链接器可以直接根据目标文件中的符号名将多个目标文件链接成一个可执行文件。
但是在C语言中,由于完全没有多态性的概念,C编译器在编译时基本对函数名什么都不会做,如test.s
中的sum
。
在上面的例子中,main.s调用的是_Z3sumii
函数,而test.c
编译出的则是sum
函数,那么链接器在链接时自然找不到函数定义而报错。
解决方法一:
为了解决这种问题,一种方法是将test.c
和main.cpp
都通过g++
编译:
xtark@xtark-vmpc:~/桌面/linux_study/section2$ g++ test.c main.cpp -o main
xtark@xtark-vmpc:~/桌面/linux_study/section2$ ./main
30
可以看出正常调用了sum
函数
解决方法二:
如果只提供了test.s
汇编文件或者test.o
目标文件,方法一就不可行。那么只能对main.cpp
下手。可以通过extern "C"
解决
main.cpp
#include <iostream>
using namespace std;
extern "C"{int sum(int a,int b);
}
int main(){int a = 10;int b = 20;cout << sum(a,b) << endl;
}
test.c
不变
在终端中输入
xtark@xtark-vmpc:~/桌面/linux_study/section2$ g++ -S main.cpp
xtark@xtark-vmpc:~/桌面/linux_study/section2$ gcc -S test.c
xtark@xtark-vmpc:~/桌面/linux_study/section2$ g++ main.s test.s
xtark@xtark-vmpc:~/桌面/linux_study/section2$ ./a.out
30
可见成功调用了sum
函数,可以通过汇编.s
代码看出原因:
test.s
没有变化
main.s
中部分内容
subq $16, %rspmovl $10, -8(%rbp)movl $20, -4(%rbp)movl -4(%rbp), %edxmovl -8(%rbp), %eaxmovl %edx, %esimovl %eax, %edicall sum
可以看出这里对于sum
函数声明是按照C语言的方式编译的,因此不再是_Z3sumii
而是sum
,因此在链接时链接器自然能够找到test.o
中的sum
函数定义。百度百科定义:加上extern "C"
后,会指示编译器这部分代码按C语言进行编译,而不是C++的。
一般在工程中,对于.c
文件定义的sum
函数,只需要在c文件的头文件中函数声明处添加extern "C"
声明,然后在cpp
文件中include
该头文件即可。注意extern "C"只有C++编译器能通过编译,C编译器无法编译会报错。
如test.h
#ifdef __cplusplus
extern "C" {#endif//...//各种函数声明int sum(int a,int b);//...
#ifdef __cplusplus
}
#endif
参考资料:
C和C++混合编译 - C++调用C
C和C++文件混合编译
C/C++ 混合编译 C++中的extern “C“相关推荐
- 如何混合编译C语言和C++
如何混合编译C语言和C++ 实际开发过程中,C++中会调用C与语言编写的代码,我在网络上面找到一篇写得很好的文章 http://blog.csdn.net/keensword/article/deta ...
- c++中的 extern C
c++中的 extern "C" 博客分类: c CC++C#GCCD语言 比如说你用C开发了一个DLL库,为了能够让C++语言也能够调用你的DLL输出(Export)的函数,你 ...
- VS2005混合编译ARM汇编代码
2019独角兽企业重金招聘Python工程师标准>>> 在开发过程中,发现简单的在Storage Memory区域拷贝或粘贴文件不能达到硬件量测的要求,需要直接通过编写ARM汇编指令 ...
- C与C++编译的区别 C和C++混合编译
原文链接,文章不错,修改了排版,看起来更加舒服. 关于extern_C 通常,在C语言的头文件中经常可以看到类似下面这种形式的代码: #ifdef __cplusplus extern "C ...
- VS里面关于.cpp文件与.cu文件混合编译问题---不要在.cpp文件声明核函数(__device__()和global__())
原文出处:点击打开链接 ############################################################# 不要在.cpp文件声明核函数,否则会报错,具体可以参 ...
- C C++混合编译问题,gcc可以编译过,但是g++编译不过(restrict引起的问题)
C C++混合编译问题 编译c c++混合的代码遇到的问题记录: 代码库中引入了string vetor等c++相关,链接的时候报错 如下: 对'std::allocator::allocator() ...
- c++与fortran混合语言编程中动态链接库的调用,[转载]C++与Fortran混合语言编程中动态连接库的调用...
摘 要:介绍了C++和Fortran 90混合语言编程中,在C++中调用Fortran动态连接库(DLL,Dynamic Link Library)的方法以及参量传递.函数调用等的方法. 关键词:混合 ...
- 何时在C ++中使用extern
本文翻译自:When to use extern in C++ I'm reading "Think in C++" and it just introduced the exte ...
- 华为鸿蒙OS发布!余承东:随时可替换安卓;方舟编译器将支持混合编译
乾明 边策 郭一璞 发自 凹非寺 量子位 报道 | 公众号 QbitAI 千呼万唤始出来,华为鸿蒙操作系统,今日正式发布. 英文名HarmonyOS,寓意为和谐. 并不像亿万行代码的安卓那样笨重,鸿 ...
- makefile多目录的.c 格式.cpp混合编译
原文地址:http://blog.csdn.net/yangbingzhou/article/details/50218315 [cpp] view plaincopyprint? # # c.cpp ...
最新文章
- python re库常用_Python re库指南
- oracle asm clsecho,ASM磁盘组一点管理
- Android下的Junit测试
- how to replace the note reuse project into my own one
- iOS应用如何支持IPV6
- mysql 5.5 主从同步问题_MySQL 5.5 主从复制异步、半同步以及注意事项详解
- 【C语言】将两个字符串连接起来
- html5的鼠标拖拽
- nparray和tensor的相互转化
- linux中哪一个标记可以作为子进程,linux系统编程试卷(答案)
- nginx开发_Filter模块执行顺序
- Zend Studio配置:使用PHP 7进行开发
- XPS文件怎么打开?可以转成PDF格式吗?
- Google商店应用上架注意事项
- 必须重启计算机才能关闭用户账户控制,Win10系统怎么彻底关闭用户帐户控制?...
- 【英语语法入门】 第29讲 情态动词的否定和疑问
- 【html】基础极速笔记
- 手把手教你用C写游程编码
- 医学统计学 第八章( t 检验)
- AutoSAR的入门知识