C++初阶第二篇——初始C++(详细讲解extern “C”)
Posted 呆呆兽学编程
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++初阶第二篇——初始C++(详细讲解extern “C”)相关的知识,希望对你有一定的参考价值。
⭐️今天·这篇博客我要来和大家一起聊一聊C++中 “extern"C” 的用处和用法,希望对大家有所帮助。
⭐️博客代码已上传至gitee:https://gitee.com/byte-binxin/cpp-class-code/tree/master
🌏extern"C"是什么?
🍤有时候在C++工程中可能需要将某些函数按照C的风格来编译,在函数前加extern “C”,意思是告诉编译器,将该函数按照C语言规则来编译。
🌏如何使用?
🍆为了让大家更好地理解extern “C”,我来给大家用静态库的方式演示一下
🌲首先创建一个静态库
🍅以“vs2019”为例,我们把自己之前写的栈放到静态库里,先创建一个空项目,然后打开项目属性,把.exe的属性改成静态库的属性就好了,如下图:
最后再编译运行一下,静态库就生成了。
这是一个c的静态库;
🌲演示C++调用C的静态库
🍅以leedcode上面的有效括号这一题为例子,给大家演示一下。(模拟实现的栈在数据结构初阶的博客中有写过,可以参考这里——栈和队列)
调用静态库之前,我们要进行一个附加库目录和附加依赖项的操作,分别如下:
第一步:
第二步:
这样一来,静态库就完全地用起来了。
下面是用C++项目调用C的静态库,没有使用extern “C”,我们看会发生什么。
#include <iostream>
using namespace std;
#include "../../Stacklib/Stacklib/Stack.h"
bool isValid(char* s)
Stack st;
StackInit(&st);
int i = 0;
while (s[i])
//左括号就插入
if (s[i] == '(')
StackPush(&st, ')');
else if (s[i] == '')
StackPush(&st, '');
else if (s[i] == '[')
StackPush(&st, ']');
else
//if (st.empty())//栈里为空,且现在为右括号就直接返回false
// return false;
if (!StackEmpty(&st) && StackTop(&st) == s[i])
StackPop(&st);
else
StackDestroy(&st);
return false;
i++;
if (StackEmpty(&st))
StackDestroy(&st);
return true;
else
StackDestroy(&st);
return false;
int main()
char str[] = "()[]";
printf("%d\\n", isValid(str));
return 0;
结果如下:
显然,在没有使用extern “C”的情况下,直接调用C的静态库编译器会报错,根本不认识静态库中的标识符。所以我们在项目前面使用extern “C”,如下:
// 告诉C++编译器,extern "C"花括号里面的内容是C编译器编译的,按C的函数的命名规则去找,就可以链接上了
extern "C"
#include "../../Stacklib/Stacklib/Stack.h"
⭐️ 这里就是告诉C++编译器,extern "C"花括号里面的内容是C编译器编译的,按C的函数的命名规则去找,就可以链接上,显然,代码很顺利地跑起来了。
🌲演示C调用C++的静态库
首先我们把先前C++的项目后缀改成 .c,把静态库的c文件改成cpp,我们试着反着来调用,会发生什么。
运行结果如下:
显然,c编译器不认识静态库中的函数。
下面是静态库头文件的内容:
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>
typedef int STDatatype;
typedef struct Stack
STDatatype* a;
int top;
int capcaity;
Stack;
//初始化栈
void StackInit(Stack* ps);
//销毁栈
void StackDestroy(Stack* ps);
//压栈
void StackPush(Stack* ps, STDatatype x);
//出栈
void StackPop(Stack* ps);
//取出栈顶元素
STDatatype StackTop(Stack* ps);
//栈的大小
int StackSize(Stack* ps);
//判断栈是否为空
bool StackEmpty(Stack* ps);
我们需要对其进行修改,让这些函数以C的方式去编译,修改后如下(两种方法):
// C++静态库,就会按照C的函数的命名规则去处理以下函数
// 第一种方法
#ifdef __cplusplus
#define EXTERN_C extern "C"
#else
#define EXTERN_C
#endif
//初始化栈
EXTERN_C void StackInit(Stack* ps);
//销毁栈
EXTERN_C void StackDestroy(Stack* ps);
//压栈
EXTERN_C void StackPush(Stack* ps, STDatatype x);
//出栈
EXTERN_C void StackPop(Stack* ps);
//取出栈顶元素
EXTERN_C STDatatype StackTop(Stack* ps);
//栈的大小
EXTERN_C int StackSize(Stack* ps);
//判断栈是否为空
EXTERN_C bool StackEmpty(Stack* ps);
//第二种方法
#ifdef __cplusplus
extern "C"
#endif
//初始化栈
void StackInit(Stack* ps);
//销毁栈
void StackDestroy(Stack* ps);
//压栈
void StackPush(Stack* ps, STDatatype x);
//出栈
void StackPop(Stack* ps);
//取出栈顶元素
STDatatype StackTop(Stack* ps);
//栈的大小
int StackSize(Stack* ps);
//判断栈是否为空
bool StackEmpty(Stack* ps);
#ifdef __cplusplus
#endif
🍆其中 __cplusplus这个宏是在cpp文件中就会有所定义,所以如果定义了这个宏,我们就定义
EXTERN_C extern “C”,否则就定义为空。
这样操作,代码也成功地跑起来了:
🌐总结
这篇博客就给大家介绍了一下如何利用extern “C”来做到C++和C之间的相互调用,总之,extern “C”总是出现在C++文件中。喜欢的话,欢迎大家点赞支持和收藏~
以上是关于C++初阶第二篇——初始C++(详细讲解extern “C”)的主要内容,如果未能解决你的问题,请参考以下文章
C++初阶第十二篇—stack和queue(stack和queue的常见接口的用法与介绍+priority_queue+容器适配器+仿函数+模拟实现)
C++初阶第三篇——初始C++(引用+内敛函数+auto关键字+范围for循环)