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
#endif
cfun.h標頭檔案中,使用了條件編譯#ifdef __cplusplus, 表示如果是c++來呼叫該介面,則該函式介面經編譯後的函式符號生成規則按照c風格走, 否則沒有extern "c" , 這樣提供的介面同時支援c和c++兩者的呼叫。
// --------------cfun.c
#include "cfun.h"
#include void cfun()
// --------------main.cpp
#include #include "cfun.h"
int main()
二、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 void cppfun()
// --------------main.c
#include extern void cppfun();
int main()
C與C 之間相互呼叫
c與c 之間相互呼叫 1 匯出c函式以用於c或c 的專案 如果使用c語言編寫的dll,希望從中匯出函式給c或c 的模組訪問,則應使用 cplusplus 預處理器巨集確定正在編譯的語言。如果是從c 語言模組使用,則用c鏈結宣告這些函式。如果使用此技術並為dll提供標頭檔案,則這些函式可以原封不動地由...
C與C 之間相互呼叫
1 匯出c函式以用於c或c 的專案 如果使用c語言編寫的dll,希望從中匯出函式給c或c 的模組訪問,則應使用 cplusplus 預處理器巨集確定正在編譯的語言。如果是從c 語言模組使用,則用c鏈結宣告這些函式。如果使用此技術並為dll提供標頭檔案,則這些函式可以原封不動地由c和c 模組使用。以下...
C與C 之間相互呼叫
1 匯出c函式以用於c或c 的專案 如果使用c語言編寫的dll,希望從中匯出函式給c或c 的模組訪問,則應使用 cplusplus 預處理器巨集確定正在編譯的語言。如果是從c 語言模組使用,則用c鏈結宣告這些函式。如果使用此技術並為dll提供標頭檔案,則這些函式可以原封不動地由c和c 模組使用。以下...