C程序如何调用C++库?C++程序如何调用C库?(visual studio)

文章目录

    • C++程序调用C库
      • 代码测试
    • C程序调用C++库
      • 测试代码

C++程序调用C库

假设现在有一个C文件,里面写了栈的实现以及相关操作,首先如何将一个C文件封装成库?

C程序如何调用C++库?C++程序如何调用C库?(visual studio)_第1张图片
对项目名右键,找到属性C程序如何调用C++库?C++程序如何调用C库?(visual studio)_第2张图片
C程序如何调用C++库?C++程序如何调用C库?(visual studio)_第3张图片
找到配置属性->常规->配置类型->改成静态库,如何重新编译文件C程序如何调用C++库?C++程序如何调用C库?(visual studio)_第4张图片
生成->重新生成解决方案,最后会生成一个.lib文件
C程序如何调用C++库?C++程序如何调用C库?(visual studio)_第5张图片

在该项目的Debug文件下能找到一个.lib文件
C程序如何调用C++库?C++程序如何调用C库?(visual studio)_第6张图片

至此一个C库生成完成。

然后写一段C++程序,里面要用到栈的相关操作,也就是要引用刚刚创建的C库。首先包含头文件,包含刚刚写的项目中的一个头文件(当然这是自己写的,写c文件时,h文件中是c文件相关函数的声明以及标准库中头文件的引用)。这里头文件的引用就是一个相对路径,…\表示该文件的上一个目录
C程序如何调用C++库?C++程序如何调用C库?(visual studio)_第7张图片
当前目录
C程序如何调用C++库?C++程序如何调用C库?(visual studio)_第8张图片
上一级目录
C程序如何调用C++库?C++程序如何调用C库?(visual studio)_第9张图片
在再上一级目录中找到刚刚写的Stack_c文件

C程序如何调用C++库?C++程序如何调用C库?(visual studio)_第10张图片
该文件路径的同名文件
C程序如何调用C++库?C++程序如何调用C库?(visual studio)_第11张图片
里面有要包含的h文件
C程序如何调用C++库?C++程序如何调用C库?(visual studio)_第12张图片
在这里插入图片描述
最后的引用路径。引用完头文件还需要配置,右键文件名,属性
C程序如何调用C++库?C++程序如何调用C库?(visual studio)_第13张图片
配置属性,链接器,输入,找到附加依赖项,把要包含的库文件写到里面,文件名最后用分号分隔
C程序如何调用C++库?C++程序如何调用C库?(visual studio)_第14张图片

C程序如何调用C++库?C++程序如何调用C库?(visual studio)_第15张图片
然后找到常规的添加库目录,将刚刚生成的库文件路径写到里面,库文件路径可以在重新生成解决方案后下面的输出找到,但路径只要写到DebugC程序如何调用C++库?C++程序如何调用C库?(visual studio)_第16张图片
C程序如何调用C++库?C++程序如何调用C库?(visual studio)_第17张图片

应用,确定。

但由于C和C++的符号表中函数修饰规则不同,C++的程序找不到一个用C写的函数,但是C++兼容C,所以在头文件包含时加上extern “C”,告诉编译器用C的规则去引用该头文件。
C程序如何调用C++库?C++程序如何调用C库?(visual studio)_第18张图片
至此,配置完成。

代码测试

// Stack的源文件,Stack.c
#include "Stack.h"

void StackInit(Stack* st)
{
	assert(st);
	st->data = NULL;
	st->top = 0;
	st->capacity = 0;
}

void StackDestory(Stack* st)
{
	assert(st);

	free(st->data);
	st->data = NULL;
	st->capacity = 0;
	st->top = 0;
}

void StackPush(Stack* st, STDataType x)
{
	assert(st);

	if (st->top == st->capacity)
	{
		//扩容,如果之前的容量是0,新的容量是4,不是0,新的容量是原来的两倍
		int newcapacity = (st->capacity == 0) ? 4 : (st->capacity * 2);
		st->capacity = newcapacity;
		st->data = (STDataType*)realloc(st->data, sizeof(STDataType) * newcapacity);
	}

	st->data[st->top] = x;
	st->top++;
}

void StackPop(Stack* st)
{
	assert(st);
	assert(st->top > 0);//top等于0,栈为空,不能删除
	st->top--;
}

bool StackEmpty(Stack* st)
{
	assert(st);

	return (st->top == 0);
}

STDataType StackTop(Stack* st)
{
	assert(st);
	assert(st->top > 0);

	return st->data[st->top - 1];
}
// Stack的头文件声明,Stack.h
#include 
#include 
#include 
#include 

typedef int STDataType;

typedef struct Stack
{
	STDataType* data;
	int top;
	int capacity;
}Stack;


void StackInit(Stack* st);
void StackDestory(Stack* st);
void StackPush(Stack* st, STDataType x);
void StackPop(Stack* st);
bool StackEmpty(Stack* st);
STDataType StackTop(Stack* st);

Stack.h和Stack.c是一个项目中的,分别对应栈的函数声明与函数定义,打包库时需要一起进行编译

// 测试源文件test.cpp
extern "C"
{
	#include "../../Stack_C/Stack_C/Stack.h"
}
#include 

int main()
{
	Stack st;
	StackInit(&st);
	StackPush(&st, 1);
	StackPush(&st, 2);
	std::cout << StackTop(&st) << std::endl;
	StackDestory(&st);
	return 0;
}

(测试程序很简单,创建并初始化一个栈,将1和2入栈,打印栈顶元素,最后销毁栈,其中与栈相关的函数是以C语言的规则打包的库)如果只是包含了Stack的头文件,编译用来测试的源文件,编译器会报链接错误,即虽然有函数的声明,编译器知道这些函数,但是在链接时编译器无法找到这些函数的定义
在这里插入图片描述
我们已经将这些函数打包成一个库,所以现在要做的的就是告诉编译器这个库的地址与名字,具体的配置过程刚才已经说了,配置库的地址与名字,并在引用头文件时加上extern “C”,让编译器以C语言的规则调用库中的函数,此时重新运行程序C程序如何调用C++库?C++程序如何调用C库?(visual studio)_第19张图片

C程序调用C++库

假设栈的实现是用C++的代码写的,那现在有一个C程序,该怎么调用这个库?两个文件的配置过程类似,这里简略带过

首先是C++文件生成静态库,过程与C文件生成C库一样C程序如何调用C++库?C++程序如何调用C库?(visual studio)_第20张图片
C程序头文件的引用
C程序如何调用C++库?C++程序如何调用C库?(visual studio)_第21张图片
依赖项和依赖路径的配置
C程序如何调用C++库?C++程序如何调用C库?(visual studio)_第22张图片
C程序如何调用C++库?C++程序如何调用C库?(visual studio)_第23张图片
需要修改的地方是:对引用的库的头文件进行条件编译。C++中有一个__cplusplus的宏,只要是C++程序就会有这个宏。由于C++是兼容C的,所以在C++程序中可以用extern “C” 的方式,告诉编译器要以C的方式去链接调用。而C程序引用这个头文件,因为条件编译,宏替换成空,extern "C"在C程序中不会出现,只会在C++程序中出现(因为C不认识extern “C”,程序会报错)。
C程序如何调用C++库?C++程序如何调用C库?(visual studio)_第24张图片
还有一种用条件编译的方式,用extern “C”{},将函数的声明包含起来,如果定义了__cplusplus这个宏,在C++程序中,extern “C”{},就会放出来。C程序中这行代码则不会放出来。

所以合理的运用条件编译可以写出兼容性强的代码
C程序如何调用C++库?C++程序如何调用C库?(visual studio)_第25张图片

测试代码

// Stack.h,C++库的头文件,需要使用extern "C"使程序以C的规则编译调用C++库

#include 
#include 
#include 
#include 


typedef int STDataType;

typedef struct Stack
{
	STDataType* data;
	int top;
	int capacity;
}Stack;

/*#ifdef __cplusplus
#define EXTERN_C extern "C"
#else
#define EXTERN_C
#endif*/

//
//EXTERN_C void StackInit(Stack* st);
//EXTERN_C void StackDestory(Stack* st);
//EXTERN_C void StackPush(Stack* st, STDataType x);
//EXTERN_C void StackPop(Stack* st);
//EXTERN_C bool StackEmpty(Stack* st);
//EXTERN_C STDataType StackTop(Stack* st);


#ifdef __cplusplus
extern "C"
{
#endif
	void StackInit(Stack* st);
	void StackDestory(Stack* st);
	void StackPush(Stack* st, STDataType x);
	void StackPop(Stack* st);
	bool StackEmpty(Stack* st);
	STDataType StackTop(Stack* st);
#ifdef __cplusplus
}
#endif
// test.c源文件,C程序不能有extern "C"
#include "../../Stack_CPP/Stack_CPP/Stack.h"
#include 

int main()
{
	Stack st;
	StackInit(&st);
	StackPush(&st, 1);
	StackPush(&st, 2);
	printf("%d\n", StackTop(&st));
	StackDestory(&st);
	return 0;
}

C程序如何调用C++库?C++程序如何调用C库?(visual studio)_第26张图片

你可能感兴趣的:(C++学习总结,c语言,c++,visual,studio)