C++中為什么有時要使用extern "C"


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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM