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”了。

如果是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++中处理。

到此这篇关于C语言与C++项目实现相互调用的文章就介绍到这了,更多相关C语言与C++ 相互调用内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Lua教程(三):C语言、C++中调用Lua的Table示例

    从写上一篇Lua的文章到现在,已经过去半月有余了,是时候让自己的Lua状态refresh一下了.本教程将介绍Lua的栈及基本栈操作,同时还有如何在C/C++代码里面读取Lua的Table. 理解Lua栈 Lua通过一个"虚拟栈"与C/C++程序进行数据交互,所有的Lua C API都是通过操作这个栈来完成相应的数据通信. Lua的这个"虚拟栈"解决了C/C++程序与Lua程序通信的两大问题: 1.Lua使用垃圾回收,而C/C++需要手动管理内存. 2.Lua使用动态

  • 在C语言中调用C++做的动态链接库

    今天在做东西的时候遇到一个问题,就是如何在C语言中调用C++做的动态链接库so文件 如果你有一个c++做的动态链接库.so文件,而你只有一些相关类的声明, 那么你如何用c调用呢,别着急,本文通过一个小小的例子,让你能够很爽的搞定. 链接库头文件: head.h class A { public: A(); virtual ~A(); int gt(); int pt(); private: int s; }; firstso.cpp #include <iostream> #include &

  • C语言代码中调用C++代码的方法示例

    由于历史原因,以及不同开发人员的技术偏好,C语言和C++语言都有一些独有的非常有价值的项目,因而两种语言的互操作,充分利用前人造的轮子是一件非常有价值的事情. C++代码调用C代码很简单,只要分别在包含的C头文件的开头和结尾加上如下的两个块: #ifdef __cplusplus extern "C" { #endif 和 #ifdef __cplusplus } #endif 即可. 然而为了支持类.重载等更加高级的特性,在编译C++代码时,C++符号会被修饰.我们dump Linu

  • C++中如何调用C语言的代码实现

    为什么要是用 extern "C" 在进行C++开发的时候,由于C.C++编译规则是不同的.C++编译函数方法是 使用mangle的技术 . void func(int age) { } void func(int age, int height) { } /*如果有这两个函数要被调用,在C语言中函数重载是不允许的,那么在C++中为什么可以呢. C++中就是使用了mangle技术,对函数重载的函数名加上编译器中自定义规则的表示符,编译之后的函数名就会不一样. 例如 func(int a

  • Lua教程(四):在Lua中调用C语言、C++的函数

    本教程将介绍如何在Lua里面调用c/c++函数. 在Lua里面调用c/c++函数其实是比较简单,本文将通过两个示例演示具体的做法:一个是求平均数,另一个是打印lua函数的一些参数信息. 最后,本文会介绍如何把这两个函数定义成一个模块,这样lua代码里面就可以不再使用全局的名字空间了. 前言 当我们需要在Lua里面调用c/c++函数时,所有的函数都必须满足以下函数签名: 复制代码 代码如下: typedef int (*lua_CFunction) (lua_State *L); 换句话说,所有的

  • C语言与C++项目实现相互调用

    目录 前言 一.C++项目调用C的静态库 二.C项目调用C++的静态库 三.总结 前言 extern “c”的作用可以实现c语言和c++相互调用. 1.当我们写c语言代码,要调用c++代码时,可以将c++的类型配置为静态库,然后直接调用头文件. 2.当我们写c++代码,要调用c代码时,可以将c的类型配置为静态库,然后直接调用头文件. 由于c++支持函数重载,而c语言不支持函数重载,c语言和c++的函数名修饰规则有所不同,所以在链接的时候就C和C++之间无法找到对应的函数地址.这时候就要引入ext

  • C语言与Lua之间的相互调用详解

    前言 第一次接触Lua是因为Unity游戏中需要热更,但是一直没搞懂Lua是怎么嵌入到别的语言中执行的,如何互相调用的. lua是扩展性非常良好的语言,虽然核心非常精简,但是用户可以依靠lua库来实现大部分工作.除此之外,lua还可以通过与C函数相互调用来扩展程序功能.在C中嵌入lua脚本既可以让用户在不重新编译代码的情况下修改lua代码更新程序,也可以给用户提供一个自由定制的接口,这种方法遵循了机制与策略分离的原则.在lua中调用C函数可以提高程序的运行效率.lua与C的相互调用在工程中相当实

  • 胶水语言Python与C/C++的相互调用的实现

    准备工作: python:https://www.python.org/downloads/ Dev-C++:https://sourceforge.net/projects/orwelldevcpp/ gcc和g++:http://mingw-w64.org/doku.php notepad++:https://notepad-plus.en.softonic.com/ 一.Python调用C 步骤1:Csayhello.c #include<stdio.h> void show_hello

  • Python与C/C++的相互调用案例

    一.问题 Python模块和C/C++的动态库间相互调用在实际的应用中会有所涉及,在此作一总结. 二.Python调用C/C++ 1.Python调用C动态链接库 Python调用C库比较简单,不经过任何封装打包成so,再使用python的ctypes调用即可. (1)C语言文件:pycall.c /***gcc -o libpycall.so -shared -fPIC pycall.c*/ #include <stdio.h> #include <stdlib.h> int f

  • python 与c++相互调用实现

    目录 一.c++调用Python 1.Python脚本 2.C++调用python脚本 二.接口方法 1.规范化语法 三.Pthon调用c++ 1.基于extern 2.基于swig 一.c++调用Python 将Python安装目录下的include和libs文件夹引入到项目中,将libs目录下的python37.lib复制一份为python37_d.lib 1.Python脚本 def Hello():     print("Hello")       def Add(a,b):

  • webservice实现springboot项目间接口调用与对象传递示例

    目录 一.百度百科 二.webservice的技术支持 1.XML和XSD 2.SOAP 3.WSDL 4.UDDI 5.调用RPC与消息传递 三.webservice的应用场景和弊端 1.webservice的应用场景 2.webservice的弊端 四.webservice代码实例 服务端项目代码 客户端项目代码: 一.百度百科 Web Service是一个平台独立的,低耦合的,自包含的.基于可编程的web的应用程序,可使用开放的XML(标准通用标记语言下的一个子集)标准来描述.发布.发现.

  • c/c++静态库之间相互调用的实战案例

    目录 一.c++项目如何调用c的库(以静态库为例) 1.将栈的源文件和头文件拷贝一份到Stack_c.lib这个项目的路径下 2.打包成静态库 3.建立一个c++项目(TestStacklib) 引入c项目中的头文件 4.设置附加库和附属关系 二.c项目如何调用c++的库(静态库为例) 1.建立c++项目(Stack_cpp) 并且将栈的源文件和头文件包含在该目录 将其打包为cpp的静态库 2.建立c项目 3.包含静态库的头文件 4 .添加打包的cpp动态库到附加库目录 设置依赖项 总结 本文主

  • Java代码中与Lua相互调用实现详解

    目录 一.方案 二.性能测试 1. ScriptEngine调用方式 2. Globals调用方式 3. lua调用java 三.结论 四.其他调用方式? 一.方案 Java与Lua相互调用案例比较少,因此项目使用需要做详细的性能测试,本内容只做粗略测试. 目前已完成初版Lua-Java调用框架开发,后期有时间准备把框架进行抽象,并开源出来,感兴趣的小伙伴欢迎关注下. 目前最常见的方案:luaj,纯Java实现的Lua解析器,基于Lua 5.2 LuaJ的原理:用Java实现了一套Lua的编译器

  • IOS开发Swift 与 OC相互调用详解

    目录 1.创建桥接文件 2.Swift调用OC NS_SWIFT_NAME.NS_SWIFT_UNAVAILABLE NS_REFINED_FOR_SWIFT 规则 3.OC调用Swift 4.坑点 1.创建桥接文件 在创建另一种语言的文件时XCode会提示创建项目名-Bridging-Header.h的桥接文件 2.Swift调用OC 1.创建OC文件 #import "MyViewController.h" @interface MyViewController () @end @

  • C#和lua相互调用的方法教程

    前言 自从ulua在官网上出来后,lua 就被u3d开发人员喜爱.国内有几个高手把lua拿过来 接着进行了封装.很多都是新手转过来.lua语法一看遍知,但是大多数人还是不明白两个语言之间的互相调用是怎么一回事,这也是难点和重点.所以今天想跟大家分享一下这方面的知识,让大家少走弯路吧. Lua是一种很好的扩展性语言,Lua解释器被设计成一个很容易嵌入到宿主程序的库.LuaInterface则用于实现Lua和CLR的混合编程. C与lua交互面临以下几个问题: 1.由于lua里面的数据都是动态加载的

随机推荐