相信從事嵌入開發(fā)的小伙伴肯定遇到過使用第三庫的情景,有時候可能是C++中調(diào)用C庫,有時候可能又是C中調(diào)用C++庫;如果你遇到過,那你肯定知道extern "C"的作用.
目前創(chuàng)新互聯(lián)建站已為數(shù)千家的企業(yè)提供了網(wǎng)站建設(shè)、域名、網(wǎng)絡(luò)空間、成都網(wǎng)站托管、企業(yè)網(wǎng)站設(shè)計、玉泉網(wǎng)站維護等服務(wù),公司將堅持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長,共同發(fā)展。本篇的目的就是給大家介紹C/C++互相調(diào)用的原理和實踐。
二、介紹首先我們需要明確以下幾點:
c++支持重載,c++中函數(shù)編譯后在符號表中的名字跟函數(shù)名本身有些區(qū)別
c不支持重載,c中函數(shù)編譯后在符號表中的名字沒有任何改動
假設(shè)我們有這樣一個頭文件print_hello.h
#ifndef PRINT_HELLO_H
#define PRINT_HELLO_H
#ifdef __cplusplus
extern "C" {
#endif
void print_hello(const char *info);
#ifdef __cplusplus
}
#endif
#endif
其中下面代碼片段的作用為了避免頭文件重復(fù)包含導(dǎo)致編譯錯誤
#ifndef PRINT_HELLO_H
#define PRINT_HELLO_H
#endif
下面的代碼片段中我們將print_hello函數(shù)根據(jù)當前使用的編譯器決定是否包含在extern "C"聲明中。如果是gcc編譯,那么__cplusplus宏是未定義的;如果是c++編譯那么print_hello函數(shù)就必須要按照C語言規(guī)范來編譯。
#ifdef __cplusplus
extern "C" {
#endif
void print_hello(const char *info);
#ifdef __cplusplus
}
#endif
extern/static關(guān)鍵字用于聲明變量或者函數(shù)的可見性,extern聲明的變量或者函數(shù)代表除了本模塊外其他模塊也可見;static聲明的變量或者函數(shù)只有本模塊可見。
我們可以通過extern聲明變量或者函數(shù)多次,但是只能定義一次。
__cplusplus只有是c++編譯器時才會定義。
關(guān)鍵字"C"是指按照C的language?linkage進行編譯鏈接。
三、實戰(zhàn)print_hello.c源代碼
#include "print_hello.h"
#includevoid print_hello(const char *info) {
printf("hello %s\n", info);
}
print_hello.h源代碼
#ifndef PRINT_HELLO_H
#define PRINT_HELLO_H
void print_hello(const char *info);
#endif
gcc編譯后查看函數(shù)符號
gcc -c print_hello.c -o print_hello.o
readelf -a print_hello.o
從上圖我們可以看到gcc編譯后的print_hello函數(shù)符號名還是print_hello。
下面我們再用g++編譯一下看下輸出結(jié)果
g++ -c print_hello.c -o print_hello.o
readelf -a print_hello.o
從上圖我們可以看到g++編譯后的print_hello函數(shù)符號名變成了_Z11print_helloPKc
下面我們來看一下通過extern?"C"?聲明編譯后的函數(shù)名稱
print_hello.h源代碼
#ifndef PRINT_HELLO_H
#define PRINT_HELLO_H
#ifdef __cplusplus
extern "C" {
#endif
void print_hello(const char *info);
#ifdef __cplusplus
}
#endif
#endif
g++編譯查看符號信息
g++ -c print_hello.c -o print_hello.o
readelf -a print_hello.o
再次看一下函數(shù)符號信息
從上圖我們可以確認通過extern "C" 限定后print_hello函數(shù)符號跟用gcc編譯后的效果一樣。
那我們再來確認一下通過g++編譯后的print_hello函數(shù)能不能被c調(diào)用
main.c源代碼
#include "print_hello.h"
int main() {
print_hello("world");
return 0;
}
gcc編譯后查看符號表
gcc main.c print_hello.o -o main
readelf?-a?main
注意print_hello.o是通過g++編譯后的目標文件
從上圖可以確認c的main程序中的確鏈接上print_hello函數(shù)。
以上,就是extern?"C"在c/c++互相調(diào)用的作用
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧