C与C++之间的相互调用(混合编程)

  • Post author:
  • Post category:其他


C和C++各自有自身的重要功能,为了能够做到充分利用,避免重复造轮子,有的时候,我们会用到混合编程。然而,我们知道,代码从编写到能执行之前,仍需要经过编译、链接阶段。通常,编译每一个单元文件会生成目标文件,然后链接器会把各个目标文件链接起来生成可执行性文件。链接器之所以能把目标文件相互之间链接起来,就是通过查找目标文件中的唯一函数符号(即经过编译器去编译修饰后,重新得到的函数符号)。但是C和C++编译器对编译函数符号的生成规则是不一样的,为什么呢?因为C只有单一的命名空间,不支持函数重载之类的特性,例如对于函数void fun(int a, int b),经过编译后生成的符号为_fun, C链接器链接的时候就会去找_fun这样的函数符号;C++为了支持函数重载(即函数名字可以相同,参数类型或个数不同),允许存在同名的函数,这一点在C中是做不到的。其实,C++甚至可以存在相同的类型、变量等,因为在C++中命名空间的存在。在C++中,对于函数void fun(int a, int b),经过编译后,生成的类似为_fun_int_int, 新生成的符号名不仅带有函数名,还有参数类型。正因为他们两者编译函数的时候,生成的符号规则不一样,所以,在混合编程中,如果我们不进行任何处理,而相互效用的话,必然会出现在链接的时候,找不到符号链接的情况。

为实现混合编程,我们不得不提到extern “C” ,

extern “C”是C++的特性,是一种链接约定,通过它可以实现兼容C与C++之间的相互调用,即对调用函数能够达成一致的意见,使用统一的命名规则,使得实现方提供的接口和调用方需要的接口经按照指定规则编译后,得到的都是一致的函数符号命名。具体用法,请看如下实例。

一、C++调用C函数实例(关键是让C++调用的C接口按照C规范走即可)

// --------------cfun.h
#ifndef __C_FUN_20180228_H__
#define __C_FUN_20180228_H__

#ifdef __cplusplus
extern "C"{
#endif // __cplusplus

	void cfun();
#ifdef __cplusplus
}
#endif


#endif

cfun.h头文件中,使用了条件编译


#ifdef __cplusplus, 表示如果是C++来调用该接口,则该函数接口经编译后的函数符号生成规则按照C风格走, 否则没有extern “C” , 这样提供的接口同时支持C和C++两者的调用。

// --------------cfun.c
#include "cfun.h"
#include <stdio.h>

void cfun()
{
	printf("hello world.\n");
}
// --------------main.cpp
#include <iostream>
#include "cfun.h"


int main()
{
	cfun();
	system("pause");
	return 0;
}

二、C调用C++函数实例(关键是让C调用的C++函数接口按照C规范走即可)

// --------------cppfun.h
#ifndef _CPP_FUN_20180228_H__
#define _CPP_FUN_20180228_H__

extern "C" void cppfun();

#endif
// --------------cppfun.cpp

#include "cppfun.h"
#include <iostream>

void cppfun()
{
	std::cout << "hello world." << std::endl;
}
// --------------main.c

#include <stdio.h>
extern void cppfun();
int main()
{
	cppfun();
	system("pause");
	return 0;
}



版权声明:本文为this_is_me_anyway原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。