链接指示:extern "C"
C++程序有时需要调用其他语言编写的函数,最常见的是调用C语言编写的函数。像所有其他名字一样,其他语言中的函数名字也必须在C++中进行声明,并且该声明必须指定返回类型和形参列表。对于其他语言编写的函数来说,编译器检查其调用方式与处理普通C++函数的方式相同,但生成的代码有所区别。C++使用链接指示(linkage directive)指出任意非C++函数所用的语言。
声明一个非C++函数:
链接指示可以有两种形式:单个或复合。链接指示不能出现在类定义或函数定义的内部。
例如:
单语句: extern "C" size_t strlen(const char *);
复合语句:extern "C" {
int strcmp(const char*, const char*);
char *strcat(char*, const char*);
}
链接指示与头文件:
复合语句:
extern "C" {
#include <string.h>
}
指向extern "C"函数的指针:
编写函数所用的语言是函数类型的一部分。(指向其他语言编写的函数的指针必须与函数本身使用相同的链接指示)
extern "C" void (*pf)(int);
当我们使用pf调用函数时,编译器认定当前调用的是一个C函数。
指向C函数的指针与指向C++函数的指针是不一样的类型。
链接指示对整个声明都有效:
当我们使用链接指示时,他不仅对函数有效,而且对作为返回类型或形参类型的函数指针也有效。
//f1是一个C函数,它的形参是一个指向C函数的指针
extern "C" void f1( void(*)(int) );
因为链接指示同时作用于声明语句中的所有函数,所以如果我们希望给C++函数传入一个指向C函数的指针,则必须使用类型别名。
//FC是一个指向C函数的指针
extern "C" typedef void FC( int );
//f2是一个C++函数,该函数的形参是指向C函数的指针
void f2(FC *);
导出C++函数到其他语言:
通过使用链接指示对函数进行定义,我们可以令一个C++函数在其他语言编写的程序中可用。
//calc函数可以被C程序调用
extern "C" double calc( double dparm ) {/*......*/}
编译器将为该函数生成适合指定语言的代码
对链接到C的预处理器的支持
有时需要在C和C++中编译同一个源文件,为了实现这一目的,在编译C++版本的程序时预处理器定义 __cplusplus(两个下划线)。利用这个变量,我们可以在编译C++程序的时候有条件地包含进来一些代码:
#ifndef __cplusplus
//正确:我们在编译C++程序
extern "C"
#endif
int strcmp( const char*, const char* );
重载函数与链接指示:
C语言不支持函数重载,因此也不难理解为什么一个C链接指示只能用于说明一组重载函数中的某一行了:
//错误:两个extern "C"函数的名字相同
extern "C" void print ( const char* );
extern "C" void print ( int );
如果在一组重载函数中有一个C函数,则其余函数必定都是C++函数。