目录
前言:
了解过c++的都知道,c++是包容c的,即c++知道c语法已经实现细节等等。那么,这样就会产生一个比较奇妙的火花--c++和c相互调用如何?
我们知道,在c与c++程序编译过程中,经历了预处理、编译、汇编、链接。而c++之所以能够支持函数重载的地方,就是因为在汇编过程中产生的符号表中,增加了函数修饰符。比如在Linux中,就是前缀+函数名+函数字符数+参数类型首字母。但是c语言里面的话,就只是单调的函数名了。
所以,想要处理c++和c库和程序相互调用的程度就要解决符号表这个问题。静态库.lib可以理解为在链接前需要合并在一起的东西,Windows下才能产生exe应用程序。
一、生成静态库
使用环境:Visual Studio 2022
使用例子:c语言所写的数据结构中的栈
1.生成c、c++静态库
首先在程序的属性页常规配置好静态库
然后对应c和cpp生成编译即可。
此时在对应路径可以找到生成的对应项目名.lib文件了,此时就是生成的c++和c静态库,但是c静态库用到c++程序里面,只有c++识别c,所以,需要在c++程序里面进行变动。但是c可识别不了c++,自然也识别不了c++静态库。
所以,此时c++库就要加上extern "C"{}将函数声明包裹起来,这样就能告诉c++这里需要用c的方式编译出来,这里的C是大写的哦。但是这样还是会出现问题。
因为c不识别extern "C"啊,所以就要用到条件编译,让c++能够识别,c不识别即可。
#ifdef __cplusplus//c++的宏
#endif
注意这里的__cplusplus是两个_哦。
这样重新生成lib文件就好啦。
二、程序链接静态库
使用环境:Visual Studio 2022
使用例子:随便调用的一些栈的函数
首先,在使用程序链接时,要在此项目增加上附加库目录增加静态库目录和设置附加依赖项为静态库名称。
上面是以c库举例。
然后就是引用头文件。因为此时头文件是在对应的库文件中,所以需要用到相对路径去寻找头文件。
上面是c++程序引用的c库的头文件。
此时运行c链接c++库就没问题了。但是c++链接c库就有问题了。因为我们并没有对c库处理过什么,要让c++识别这是c的静态库的话同样用到extern "C"即可。
此时运行程序,大功告成。
三、所用到的源码:
void test1()
{
ST s;
StackInit(&s);
StackPush(&s, 3);
StackPush(&s, 2);
StackPush(&s, 1);
printf("%d\n", StackSize(&s));
printf("%d\n", StackTop(&s));
StackPop(&s);
printf("%d\n", StackSize(&s));
printf("%d\n", StackTop(&s));
StackPop(&s);
printf("%d\n", StackSize(&s));
printf("%d\n", StackTop(&s));
StackPop(&s);
printf("%d\n", StackSize(&s));
/*StackDestroy(&s);*/
}
int main()
{
test1();
return 0;
}
//头文件
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include <stdbool.h>//能够让c语言使用布尔类型的c语言
//数据类型
typedef int STDataType;
//定义栈的结构 我们用数据结构来表示
typedef struct Stack
{
STDataType* x;
int top;//实时储存
int capacity;//容量
}ST;
extern "C"
{
//初始化函数
void StackInit(ST* ps);
//将此栈摧毁
void StackDestroy(ST* ps);
//压栈
void StackPush(ST* ps, STDataType x);
//出栈
STDataType StackTop(ST* ps);
//出栈 弹出数据
void StackPop(ST* ps);
//判断是否存在数据
bool StackEmpty(ST* ps);
//当前存在的数据个数
int StackSize(ST* ps);
}
#include"Stack.h"
//初始化函数
void StackInit(ST* ps)
{
assert(ps);
ps->x = NULL;
ps->top = 0;
ps->capacity = 0;
}
//摧毁栈
void StackDestroy(ST* ps)
{
assert(ps);
free(ps->x);
ps->x = NULL;
ps->top = 0;
ps->capacity = 0;
}
//压栈 实际上在顺序表的基础上禁止了头插而已,所以实际上就是一个尾插而已
void StackPush(ST* ps, STDataType x)
{
assert(ps);
//第一类情况:首次进来和容量不足的情况
if (ps->top == ps->capacity)
{
int newcapcity = (ps->capacity == 0) ? 4 : (ps->capacity) * 2;//三目运算符确定
STDataType* temp = (STDataType*)realloc(ps->x, sizeof(STDataType));
if (temp == NULL)
{
printf("芭比扣了.jpg\n");
exit(-1);
}
ps->x = temp;
ps->capacity = newcapcity;
}
ps->x[ps->top] = x;
ps->top++;
}
//出栈 -输出数据
STDataType StackTop(ST* ps)
{
assert(ps);
assert(!StackEmpty(ps));//确保里面还存在数据
return ps->x[ps->top - 1];
}
//出栈 弹出数据
void StackPop(ST* ps)
{
assert(ps);
assert(!StackEmpty(ps));
ps->top--;
}
//判断是否存在数据
bool StackEmpty(ST* ps)
{
assert(ps);
return ps->top == 0;
}
int StackSize(ST* ps)
{
assert(ps);
return ps->top;
}
上述代码仅供参考。