当前位置:   article > 正文

C++基础知识之extern “C“的用法。_c++ extern "c

c++ extern "c
  • 概述

有时候在C++的工程中可能需要将某些函数按照C的风格来编译,在函数前加extern “C”,意思是告诉编译器,将该函数按照C语言规则来编译。这里通俗的讲就是,在C++的工程中我们可以包含一个头文件,调用一些用C语言格式写的函数。同样的在C的工程中我们也可以包含其它C++工程头文件,调用C++源文件中的函数。接下来就分别介绍这两种用法,和其中原理。

  • C++项目调用C文件的函数

我新建一个C++项目然后调用C写的栈这种数据结构为例来进行说明。新建一个C的项目命名位static base,从以前的栈的项目中复制头文件stack.h,里面是栈的建立,各种操作函数的声明,并且也复制源文件stack.c,里面就是头文件中各函数的实现,将这两个文件复制到刚新建的static base 工程下。
在这里插入图片描述
右击源文件添加现有项将stack.c添加进来,右击头文件添加现有项将stack.h添加进来。我们待会是要用C++项目来使用这里C写的栈。首先完成以上步骤后,我们要将static base这个项目改一下属性,以便后面用C++调用这里的函数。
在这里插入图片描述
右击图示位置选择属性到以下界面,将配置类型由应用程序改为静态库,就是变为由其他工程调用的库,这里最后将data base 编译成后缀为.lib的文件而不是可执行程序。
在这里插入图片描述
在这里插入图片描述
这就是现成的C的静态库,接下来我们新建一个C++的项目,在其中调用这个静态库,使用C文件中的函数,新建C++项目命名为test_12_2(随便命名),创建一个源文件命名test.cpp,我们就调用C中的函数在.cpp文件中完成一些简单的操作来练习extern "C"的用法。在test_12_2的项目中要调用static base中的函数也要对属性进行一些设置。
首先在属性,链接器,常规,附加库目录中点下拉箭头添加我们准备调用的静态库的路径,选中我们准备调用的项目static base下的Debug,因为我们刚刚在static base中编译生成的.lib文件就在Debug下。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
第二步,点击输入在附加依赖项栏中前面添加项目名加.lib后缀和分号,即static base.lib;
在这里插入图片描述
完成两步设置点应用加确定,一定要注意是在你准备调用的静态库项目中将属性改成静态库.lib这里是static base,在你准备操作调用其他静态库项目的项目中改以上两处位置属性,这里是test_12_2
下面就可以在test_12_2项目中在C++中用到C写的栈了,首先要用#include命令把另一个项目中的stack.h包含进来,要包含不在同一个项目中的头文件,就只能返回上一层路径去找。

#include"../../static base/stack.h"
  • 1

这里. . 两个符号就是从test_12_2这一层再向上一层去找static base这个项目,在这个项目往下找到stack.h。
在.cpp中预处理时就会把stack.h给展开,这时本文要介绍的主角extern "C"就登场了。

extern "C"
{
#include"../../static base/stack.h"
}
  • 1
  • 2
  • 3
  • 4

展开后有了extern “C”,它就会告诉编译器下面范围内的函数按C语言的风格来编译,在链接环境按C的函数命名规则去相应文件符号表中找相应函数的地址。
下面是在.cpp中调用C的函数的测试代码和效果。

extern "C"
{
 #include"../../static base/stack.h"
}
#include<iostream>
using namespace std;
void print(int* a, int n)
{
	for (int i = 0; i < n; i++)
		printf("%d ",a[i]);
	printf("\n");
}
int main()
{
	Sta  N;
	stackinit(&N);
	stackpush(&N, 1);
	stackpush(&N, 2);
	stackpush(&N, 3);
	stackpush(&N, 4);
	stackpush(&N, 5);
	stackpop(&N);
	stackpop(&N);
	print(N.a, N.top);
	
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

在这里插入图片描述

  • C项目中调用C++文件格式的函数

这里与上面是非常类似的,可以通过把static base中的stack.c后缀改成.cpp,这就是C++格式的函数了,然后将test_12_2的test.cpp改成test.c,在这里调用static base中的函数,这就是在C的项目中调用C++的函数了。
这里的关键点是,在包含stack.h后test_12_2在C的格式下编译会出错,因为C是没有extern "C"的,它不认识这种语法,只有C++才认识,这里要用到条件编译。

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

typedef int Datatype;
typedef struct stack
{
   Datatype* a;
   int top;
   int capacity;
}Sta;

#ifdef __cplusplus
extern "C"
{
#endif 
   void stackinit(Sta* st);   //栈的初始化
   void stackdestory(Sta* st);   //栈的销毁
   void stackpush(Sta* st, Datatype x);  //数据入栈
   void stackpop(Sta* st);            //数据出栈
   Datatype stacktop(Sta* st);     //获得栈顶数据
   int  stacksize(Sta* st);          //计算栈数据元素个数
   bool stackEmpty(Sta* st);     //栈为空返回真  否则返回假
#ifdef __cplusplus
}
#endif
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

现在是C++格式的栈,要在C项目中调用它。在static base 中编译,因为是C++格式下,有__cplusplus的标识符,所以这里的函数声明都会包含在extern "C"中,而在test_12_2中包含了stack.h,在这里C格式下展开后没有__cplusplus的标识符,条件编译为假,最后只会编译函数声明,extern "C"不会被编译,extern "C"就会告诉编译器这些函数按C的风格去编译和链接。还有另一种使用条件编译的方法使extern "C"在C++下编译,在C下不编译。

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

EXTERN_C	void stackinit(Sta* st);   //栈的初始化
EXTERN_C	void stackdestory(Sta* st);   //栈的销毁
EXTERN_C	void stackpush(Sta* st, Datatype x);  //数据入栈
EXTERN_C	void stackpop(Sta* st);            //数据出栈
EXTERN_C	Datatype stacktop(Sta* st);     //获得栈顶数据
EXTERN_C	int  stacksize(Sta* st);          //计算栈数据元素个数
EXTERN_C	bool stackEmpty(Sta* st);     //栈为空返回真  否则返回假
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

测试代码和测试结果

#include"../../static base/stack.h"

void print(int* a, int n)
{
	for (int i = 0; i < n; i++)
		printf("%d ",a[i]);
	printf("\n");
}
int main()
{
	Sta  N;
	stackinit(&N);
	stackpush(&N, 1);
	stackpush(&N, 2);
	stackpush(&N, 3);
	stackpush(&N, 4);
	stackpush(&N, 5);
	print(N.a, N.top);
	
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/264347
推荐阅读
相关标签
  

闽ICP备14008679号