【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++文件中。喜欢的话,欢迎大家点赞支持和收藏~
在这里插入图片描述

  • 18
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 15
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

呆呆兽学编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值