日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

C語言與C++項目實現相互調用_C 語言

作者:想學好編程的小菜鳥 ? 更新時間: 2022-03-31 編程語言

前言

extern “c”的作用可以實現c語言和c++相互調用。

1.當我們寫c語言代碼,要調用c++代碼時,可以將c++的類型配置為靜態庫,然后直接調用頭文件。

2.當我們寫c++代碼,要調用c代碼時,可以將c的類型配置為靜態庫,然后直接調用頭文件。

由于c++支持函數重載,而c語言不支持函數重載,c語言和c++的函數名修飾規則有所不同,所以在鏈接的時候就C和C++之間無法找到對應的函數地址。這時候就要引入extern “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語言的函數修飾規則修飾,而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中沒有定義__cplusplus,這樣C項目調用時,將E替換為空 ,直接展開函數聲明。

三、總結

1??通過extern "C",我們可以實現C項目調C++的庫,C++項目調C的庫。不需要源碼,只需要靜態庫和頭文件就可以實現功能。

2??在多人協作時尤為方便,只需要將寫好的代碼配置成.lib的靜態庫,然后將頭文件一起打包發給對方,對方在不知道具體的源碼和函數的實現下,只需要知道函數的功能就可以直接調用,也加強的多人協作之間的保密性

3??因為extern "C"只在C++中 起作用,所以不管是調用C的庫還是C++的庫,extern "C"都只在C++中處理。

原文鏈接:https://blog.csdn.net/weixin_46016019/article/details/122192435

欄目分類
最近更新