extern "C"的作用
在C++引用lua的頭文件時,我們總會寫成:
extern "C" {
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
}
為什么要這么做呢?原因是C++的編譯器會對程序中符號進行修飾,這個過程在編譯器中叫符號修飾(Name Decoration)或者符號改編(Name Mangling)。
同時我們知道C++是能夠兼容C的,如果我們有了一個C語言的頭文件和其對於的庫,在C++中如何使用它呢?在include該頭文件的時候當然要加入extern "C",否則按照C++的符號進行符號修飾,那么在庫中就會找不到該符號了。
為了加深印象,再看一個例子:
//a minimum program to test why extern "C" is need in C++
#include<stdio.h>
namespace myname {
int var = 42;
}
extern "C" int _ZN6myname3varE;
int main()
{
printf("%d\n", _ZN6myname3varE);
myname::var ++;
printf("%d\n", _ZN6myname3varE);
printf("%p\n",&_ZN6myname3varE);
printf("%p\n", &myname::var);
return 0;
}
編譯執行結果:
$:~/blog/lua$ g++ extern_c.cc
$:~/blog/lua$ ./a.out
42
43
0x601040
0x601040
在這個例子中,我們根據g++編譯器的符號修飾規則,仿造了一個C變量(gcc不進行符號修飾),欺騙了編譯器,把myname::var 和 _ZN6myname3varE當成了同一個變量了。這怎么有點像是c++中的引用?這里還是有些不是很理解。
還有另外一個問題,C語言不支持extern "C"語法,如果我們想寫一個頭文件,同時支持被C和C++引用,該怎么辦?可以使用C++的宏 "__cplusplus"來判斷是不是C++編譯器。
#ifdef __cplusplus
extern "C" {
#endif
// 正式定義。。。
#ifdef __cplusplus
}
#endif
--程序員的自我修養:鏈接、裝載與庫/俞甲子,石凡,潘愛民著。—北京:電子工業出版社,2009.4 ISBN 978-7-121-08511-6