C语言调用C++中的函数,extern "C"的含义

C++编译器在将cpp文件编译成库时,导出的函数名会改变,成员函数会通过加一些元素变成全局函数,如果这时候我们需要用C语言调用C++的函数,就有了一个问题,那就是不知道C++库中导出的函数名,这是由编译器决定的,这个时候就需要用到extern关键字。例子:
test.cpp:

int add(int a, int b)
{
    return a+b;    
}

编译:

g++ -o test.o -c test.cpp
nm -s test.o

输出:

0000000000000000 T _Z3addii

查看test.o的符号表,可以发现,并没有add函数,而是有一个_Z3addii的函数名,这就是C++编译器编译之后的函数名,如果我们需要调用此函数,那么就需要使用这个函数名。
main.c:

#include<stdio.h>
int main()
{
    int i = _Z3addii(1,2);
    printf("i = %d\n",i);
    return 0;
}

编译链接:

gcc -o main.o -c main.c
gcc -o main main.o test.o
./main

输出为:

i = 3

说明调用成功,我们不可能每个需要调用的函数都这么查看函数名,使用这种方法来调用C++函数显然是不可行的,这个时候就需要extern关键字了,修改test.cpp如下:
test.cpp:

extern "C"
{
    int add(int a, int b);
}

int add(int a, int b)
{
    return a+b;
}

编译:

g++ -o test.o -c test.cpp
nm -s test.o

输出为:

0000000000000000 T add

这时就可以通过add直接来调用该函数了,extern "C"的含义就是告诉编译器,下面的函数使用C风格来编译,C语言编译时就不会修改函数名,因为没有重载,类,命名空间等这些概念,函数名是唯一的,而C++因为有类、命名空间、函数重载这些概念,所以函数名可能是相同的,所以C++编译器会修改函数名,使得两个相同函数名的函数在调用时不会产生冲突。比如有两个类test1和test2,它们都有同名函数add,这时C++编译器就会将test1中的add编译成类似xxtest1xaddxx这样的函数名,test2中的add会被编译成类似xxtest2xxaddxx的函数名,这样调用函数就不会冲突了。
修改main.cpp:

#include<stdio.h>

extern "C" {
	int add(int a, int b);
}

int main()
{
    int i = add(1,2);
    printf("i = %d\n",i);
    return 0;
}

这时编译器在编译时,遇到extern “C”, 发现里面包含了add函数,这时在遇到调用add函数的时候,就会使用C风格的样式来调用add函数,将main.cpp编译为汇编文件可以看到在调用add时如下所示:

call add

而没有使用extern "C"时,调用add时如下:

call _Z3addii

要调用成功,必须保证调用者的函数和被调用者中导出的函数名要一致,在main.cpp中添加extern用于将调用者的函数名设置为add,在test.cpp中使用extern 用于将被调用者的函数名设置为add,这样在链接的时候才会匹配上,从而链接成功

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值