【C++】vs2019建立静态库 + extern “C“ 的实例详解


在这里插入图片描述

使用场景

我们在C++中需要调用C的库时会需要使用 extern "C"

1.C++调用C

我们以leetcode20.有效的括号为例,答案点这里,这道题我们用C写了一个栈的函数库方便调用。
在这里插入图片描述

1.我们将main函数以及题目提供的接口函数放置在C++的工程文件test1的源文件test.cpp中:

//test.cpp

bool isValid(char* s)
{}

int main()
{}

2.我们将栈的函数制成C的静态库

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

用到栈的函数
在这里插入图片描述
在这里插入图片描述
栈函数的编写见这里

3.然后按f7键对这个静态库进行编译,随后会在DS目录的debug文件夹中找到相应的lib文件。

在这里插入图片描述

4.然后在C++中调用C的静态库头文件

注意这里调用的方式
../——表示寻回上一层文件
在这里插入图片描述
再对C++工程文件进行设置
a.附加库目录(DS下的Debug文件):

在这里插入图片描述
b.附加依赖项:DS.lib;(不要漏掉分号)
在这里插入图片描述
这时,我们按下f7进行编译,发生报错:
在这里插入图片描述
由于C和C++对函数名修饰规则的不一致,导致C++无法在C静态库找到中对应名字的函数,使用不了C编译的静态库。

5.这时extern "C" 派上用处了!

用法如下↓
在这里插入图片描述
这时再编译test.c
在这里插入图片描述
调用成功!


2.C调用C++

当我们编写C语言需要使用C++库时,同样可以使用extern "C"

1.C文件放main函数和接口函数

在这里插入图片描述

2.建立C++静态库存放栈函数并编译产生lib文件,与上面一致,这里不再赘述

在这里插入图片描述

3.我们继续在C文件中写上调用,并且对附加库目录附加依赖项进行设置,然后先按f7试下能否调用

报错
在这里插入图片描述
c++中的函数名是被修饰的,C文件对其进行调用依然因为函数名修饰的规则不同,而找不到相应的函数。

4.这里我们同样可以利用extern "C" , 使C++静态库以C的函数名修饰规则去处理函数,从而让C文件识别出这些函数并顺利调用。

由于C++静态库的头文件预处理后在C的工程文件下展开,而C的语法规则中不包含extern "C"
在这里插入图片描述

我们就做一些小小的改变,使C++静态库以C的函数名修饰规则去处理栈函数,又可以让C在调用时避开extern “C”——条件编译
条件编译的第一种方法

#ifdef __cplusplus
extern "C"
{
#endif
	
	//初始化栈
	void StackInit(ST * ps);

	//销毁栈
	void StackDestroy(ST* ps);

	void StackPush(ST* ps, STDataType x);//压栈

	void StackPop(ST* ps);//弹栈

	//当前栈的大小
	int StackSize(ST* ps);

	//获取栈顶元素
	STDataType StackTop(ST* ps);

	//栈是否为空
	bool StackEmpty(ST* ps);
	
#ifdef __cplusplus
}
#endif 

解释:第一次编译时是C++静态库建立的过程,在C++文件下编译,__cplusplus处于激活状态(__cplusplus的值是为了表示C++的版本),可以使用extern "C"对C++静态库以C的函数名修饰规则去处理函数,随后生成lib文件。
第二次编译时已在C工程环境下,__cpluscplus没有定义,可以跳过extern "C",所以C可以直接调用这些符合C函数命名规则的函数了。
条件编译的第二种方法

#ifdef __cplusplus
#define EXTERN_C extern "C"//以C的命名规则去修饰函数
#else
#define EXTERN_C
#endif

//初始化栈
EXTERN_C void StackInit(ST* ps);

//销毁栈
EXTERN_C void StackDestroy(ST* ps);

EXTERN_C void StackPush(ST* ps, STDataType x);//压栈

EXTERN_C void StackPop(ST* ps);//弹栈

//当前栈的大小
EXTERN_C int StackSize(ST* ps);

//获取栈顶元素
EXTERN_C STDataType StackTop(ST* ps);

//栈是否为空
EXTERN_C bool StackEmpty(ST* ps);

C++文件按f7重新编译生成lib后,再对C文件运行
在这里插入图片描述
调用成功


总结

1.C++调用C的库

在C++程序调用的库前添加extern "C"
在这里插入图片描述
设置附加库目录附加依赖项,可链接到C静态库。

2.C调用C++的库

在C++库中加extern "C" (条件编译)进行编译生成lib,
在C中可直接调用C++静态库
在这里插入图片描述
源代码戳这里


青山不改 绿水长流

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>