IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> extern “ C “,实现C与C++项目的相互调用 -> 正文阅读

[C++知识库]extern “ C “,实现C与C++项目的相互调用

目录

前言

一、C++项目调C的静态库。

二、C项目调用C++的静态库

?三、总结



前言

extern “c”的作用可以实现c语言和c++相互调用。

1.当我们写c语言代码,要调用c++代码时,可以将c++的类型配置为静态库,然后直接调用头文件。

2.当我们写c++代码,要调用c代码时,可以将c的类型配置为静态库,然后直接调用头文件。

由于c++支持函数重载,而c语言不支持函数重载,c语言和c++的函数名修饰规则有所不同,所以在链接的时候就C和C++之间无法找到对应的函数地址。所以引入extern “C”。

1.在C++项目中调用C的静态库时,告诉C++编译器,extern "C"{}里面的函数是C编译器编译的,链接的时候用C的函数名规则去找,就可以链接上。

2.在C项目中调用C++的静态库时,同样告诉C++编译器,extern "C"{}里面的函数要用C语言的修饰规则修饰。

下面我们通过代码来了演示,实验环境:VS2019。

一、C++项目调用C的静态库

我们先将写好的C程序配置成.lib的静态库:

此时该静态库的debug目录下就有.lib的静态库

然后在需要调用库的C++项目中,引入静态库:

将附加库目录的路径设置为配置好的静态库的debug路径下。

然后在链接器的输入下添加? c的lib.lib;(创建的项目名.lib)

?调用静态库的C++代码:

其中include内的 ..是跳转到上一级目录。

#include <iostream>

using namespace std;
// C++项目
// 告诉C++编译器,extern "C"{}里面的函数是C编译器编译的,链接的时候用C的函数名规则去找,就可以链接上
extern "C"
{
	#include "../c的lib/Stack.h"
}

bool isValid(const char * s){
	ST st = { 0 };
	StackInit(&st);
	while (*s)
	{
		if (*s == '('
			|| *s == '{'
			|| *s == '[')
		{
			StackPush(&st, *s); 
			++s;
		}
		else
		{
			// 遇到右括号了,但是栈里面没有数据,说明
			// 前面没有左括号,不匹配,返回false
			if (StackEmpty(&st))
			{
				StackDestroy(&st);
				return false;
			}

			STDataType top = StackTop(&st);
			StackPop(&st);
			if ((*s == '}' && top != '{')
				|| (*s == ']' && top != '[')
				|| (*s == ')' && top != '('))
			{
				StackDestroy(&st);
				return false;
			}
			else
			{
				++s;
			}
		}
	}

	// 如果栈不是空,说有栈中还有左括号未出
	// 没有匹配,返回是false
	bool ret = StackEmpty(&st);
	StackDestroy(&st);
	return ret;
}

int main()
{
	cout << isValid("{[]}") << endl;
	cout << isValid("([)]") << endl;

	return 0;
}

配置静态库的c代码:

Stcak.h

#pragma once

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>

typedef int STDataType;
typedef struct Stack
{
	STDataType* a;
	int top;
	int capacity;
}ST;

void StackInit(ST* ps);
void StackDestroy(ST* ps);
void StackPush(ST* ps, STDataType x);
void StackPop(ST* ps);
STDataType StackTop(ST* ps);
int StackSize(ST* ps);
bool StackEmpty(ST* ps);

Stack.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "Stack.h"


void StackInit(ST* ps)
{
	assert(ps);
	ps->a = NULL;
	ps->top = 0; // ps->top = -1;
	ps->capacity = 0;
}

void StackDestroy(ST* ps)
{
	assert(ps);
	free(ps->a);
	ps->a = NULL;
	ps->capacity = ps->top = 0;
}

void StackPush(ST* ps, STDataType x)
{
	assert(ps);

	if (ps->top == ps->capacity)
	{
		int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		STDataType* tmp = (STDataType*)realloc(ps->a, sizeof(STDataType) * newCapacity);
		if (tmp == NULL)
		{
			printf("realloc fail\n");
			exit(-1);
		}

		ps->a = tmp;
		ps->capacity = newCapacity;
	}

	ps->a[ps->top] = x;
	ps->top++;
}

void StackPop(ST* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));

	ps->top--;
}

STDataType StackTop(ST* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));

	return ps->a[ps->top - 1];
}

int StackSize(ST* ps)
{
	assert(ps);

	return ps->top;
}

bool StackEmpty(ST* ps)
{
	assert(ps);

	/*if (ps->top == 0)
	{
		return true;
	}
	else
	{
		return false;
	}*/
	return ps->top == 0;
}

二、C项目调用C++的静态库

实现方法与上面类似。只需要将上面步骤的.cpp与.c文件后缀互换,然后通过条件编译,将C++静态库中的头文件的函数用extern"C"作用:

#pragma once

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>

typedef int STDataType;
typedef struct Stack
{
	STDataType* a;
	int top;
	int capacity;
}ST;

//void StackInit(ST* ps);
//void StackDestroy(ST* ps);
//void StackPush(ST* ps, STDataType x);
//void StackPop(ST* ps);
//STDataType StackTop(ST* ps);
//int StackSize(ST* ps);
//bool StackEmpty(ST* ps);


#ifdef __cplusplus
 extern "C"
 {
#endif

	 void StackInit(ST* ps);
	 void StackDestroy(ST* ps);
	 void StackPush(ST* ps, STDataType x);
	 void StackPop(ST* ps);
	 STDataType StackTop(ST* ps);
	 int StackSize(ST* ps);
	 bool StackEmpty(ST* ps);

#ifdef __cplusplus
 }
#endif

其中__cplusplus是c++中定义好的宏。所以在c++中就会展开extern "C"{}

,而c项目调用头文件时,就没有__cplusplus这个宏就不会展开extern "C"{}。

还有另一种条件编译:

#ifdef __cplusplus
#define E extern "C"
#else
#defien E
#endif

E void StackInit(ST* ps);
E void StackDestroy(ST* ps);
E void StackPush(ST* ps, STDataType x);
E void StackPop(ST* ps);
E STDataType StackTop(ST* ps);
E int StackSize(ST* ps);
E bool StackEmpty(ST* ps);

然后在C项目中调用头文件#include "../c的lib/Stack.h",这样C项目调用时,将E替换为空 ,直接展开函数。

?三、总结

1??通过extern "C",我们可以实现C项目调C++的库,C++项目调C的库。不需要源码,只需要静态库和头文件就可以实现功能,多人协作时非常方便。

2??因为extern "C"只在C++中 起作用,所以不管是调用C的库还是C++的库,extern "C"都只在C++中处理。

不是看到希望才去坚持,而是坚持了才看到希望,敬每一位努力奋斗的你和学习编程的你。希望我的文章能对你有所帮助。欢迎👍点赞 ,📝评论,🌟关注,??收藏

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-01-01 13:42:06  更:2022-01-01 13:43:55 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 10:26:43-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码