C和C++互相调用动态库

平时需要接触c和c++,有时会遇到两种语言互相调用动态库的情况,这时就要对代码进行一些处理,做个记录。

前提
两种语言生成的库是无法直接互相调用的,原因在于c++支持重载,因此存在改名机制(也可能是因为有改名机制所以支持重载 ==!)_,即生成的中间文件会对函数名进行改写,会将函数名与参数列表相结合生产新的函数名,这样就可以通过不同的函数名来区分重载函数了。
而C语言没有改名机制,函数名未改动,若两种语言直接调用,便会报错:函数名未定义。
eg:
C++代码 ,cplus.cpp 和 cplus.h

#include<stdio.h>
int sayCplus()
{
    printf("Hello, C++\n");
    return 0;
}
#ifndef _CPLUS_H_
#define _CPLUS_H_

int sayCplus();

#endif

C 代码,c.c和c.h

#include<stdio.h>
int sayC()
{
    printf("HI, This is C program\n");
    return 0;
}
#ifndef _C_H_
#define _C_H_

int sayC();

#endif

分别编译成动态库libCplus.so和libC.so
用nm 指令查看,可知函数sayCplus在动态库中被改名了。

这时若用c调用libCplus.so,或c++调用libC.so,会显示对函数xxx未定义的引用。

C调用C++动态库 ——即把C++以C方式编译
要实现C调用C++的动态库,需要使用"extern C"关键字。该关键字是C++之父在设计C++时,为兼容已存在的大量C代码而设定的方法。用该关键字将C++的函数包含起来,即可将C++按C语言的方式进行编译。
改写如上代码cplus.cpp

#include<stdio.h>

extern "C"
{
int sayCplus()
{
    printf("Hello, C++\n");
    return 0;
}
}

重新编译成动态库libCplus.so,该函数不会被再改名,就可以调用了。

注意:
<1>只在cpp中使用extern “C”,若其他c++代码包含了该头文件并调用动态库仍会报错,因为头文件中的函数是按c++方式(改名机制)寻找。
因此,若c++生成的动态库要供c 和 c++调用,需要将cpp和头文件中的函数都用extern "C"包含起来。
也可只在头文件中用extern "C"括起来,在cpp中包含该头文件,效果如上。
<2>用该方法C++就无法实现重载了。
<3>若C++函数的参数中使用了C中不存在的数据类型(如vector、string),或是包含了代码中的其他结构,则用extern "C"包含并不能编译通过。此时可以通过对该函数再封装一层,入参、出参确保是通用类型即可。

C++调用C动态库
C++动态库也要用到extern "C"关键字,但是用在头文件中。
先将C语言的头文件用extern "C"包起来,c++中include该头文件,即会以c的方式去寻找函数,即可实现c++调用c动态库。
注意:用extern "C"包涵后,该头文件就无法给c语言调用使用了,因此一般会加个宏定义__cplusplus,
判断是用c++的方式编译,则extern “C” 生效。
改后的头文件如下:

#ifndef _C_H_
#define _C_H_

#ifdef __cplusplus
extern  "C"
{
#endif

int sayC();

#ifdef __cplusplus
}
#endif

#endif

注意:该种方式,c的动态库并不用改变。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值