您好,登錄后才能下訂單哦!
一、C 或 C++ 編譯的四個步驟
(一) 預處理
在該步驟中,編譯器將源程序中以“#”開頭的語句進行處理。其中,#include 的原理是將目標文件內容導入本文件。
(二) 編譯
在該步驟中,編譯器將第一步生成的各個文件分別轉換成匯編語言文件。在該過程中,所有函數的名稱都會被轉換成一個符號作為匯編文件中的唯一標識,對 C 語言函數一般直接用函數名稱作為其唯一標識的符號,而對于 C++ 函數在多數情況下需要在函數名稱加上各種前綴或后綴才能作為其標識,比如函數 void Print(int num),如果編譯器將其視為 C 語言編譯,則該函數在匯編文件中的符號為 Print,若視為 C++,則其符號可能為 Print_int(在 gcc 或 g++ 中函數名稱的改變還會考慮命名空間等因素),這也是 C++ 支持函數重載的原因。
(三) 匯編
在該步驟中,編譯器將第二步生成的各個文件分別轉換為二進制文件,但還不是可執行文件。
(四) 鏈接
在該步驟中,編譯器會為第三步生成的每一個文件“穿針引線”,比如 main() 函數中調用了 Print() 函數,還不知道 Print() 函數在哪里,而在 Print() 函數主體所在的那個文件中,已經標明了 Print() 函數的地址,所以編譯器會在 main() 函數中調用 Print() 函數的地方標注 Print() 函數的地址,為程序執行過程中的地址跳轉提供目標地址,而編譯器能做到這一步的前提,是 main() 函數中 Print() 函數的標識,和 Print() 函數主體所在的那個文件中 Print() 函數的標識是一模一樣的,如果不一樣,就會觸發鏈接錯誤。
二、C 與 C++ 接口相互調用的關鍵
從上文可以得知,要調用一個函數有一個重要條件就是調用處的符號和函數主體處的符號要一模一樣,而 C 和 C++ 在編譯過程中將函數名稱改編成標識符號的方法是不一樣的,因此相互調用的關鍵在于統一接口函數的標識符號,而一般采取的方法是,用 C 函數改編的方法統一接口函數的改編方式。
三、extern "C"
extern "C" 的作用是告訴編譯器按 C 函數名稱改編的方法將修飾的函數改編成標識符號。extern "C" 一般用在 C++ 文件中。
extern "C" void Print(int num); extern "C" { void Input(int* num); void Output(int num); };
以上是 extern "C" 的兩種寫法。如此一來,以上三個函數都會按 C 的方式被改編成符號,在 gcc 或 g++ 編譯下就會被改變成 Print,Input,Output。
四、C 函數調用 C++ 接口
(一) 調用非成員函數
被調用函數的聲明和定義如下。
/** * called.h */ #ifndef CALLED_H #define CALLED_H extern "C" void PrintCpp(void); #endif
/** * called.cpp */ #include <iostream> #include "called.h" using namespace std; void PrintCpp(void) { cout << "I\'m cpp." << endl; }
最終調用如下。
/** * call.c */ #include "called.h" int main(int argc, char const* argv[]) { PrintCpp(); return 0; }
(二) 調用類成員函數(接口函數沒有類指針)
被調用函數聲明和定義如下。
/** * called.h */ #ifndef CALLED_H #define CALLED_H class Console { public: Console(); virtual void PrintDouble(double num); }; extern "C" void CppPrintDouble(double num); #endif
/** * called.cpp */ #include <iostream> #include "called.h" using namespace std; Console::Console() {} void Console::PrintDouble(double num) { cout << num << endl; } Console* console = new Console(); void CppPrintDouble(double num) { console->PrintDouble(num); }
最終調用如下。
/** * call.c */ #include "called.h" int main(int argc, char const* argv[]) { CppPrintDouble(3.14); return 0; }
五、C++ 函數調用 C 接口
被調用函數的聲明和定義如下。
/** * called.h */ #ifndef CALLED_H #define CALLED_H void PrintC(void); #endif
/** * called.c */ #include <stdio.h> #ifdef __cplusplus extern "C" { #endif #include "called.h" #ifdef __cplusplus }; #endif void PrintC(void) { printf("I\'m C.\n"); }
最終調用如下。
/** * call.cpp */ #ifdef __cplusplus extern "C" { #endif #include "called.h" #ifdef __cplusplus }; #endif int main(int argc, char const* argv[]) { PrintC(); return 0; }
在 called.c 文件中,#ifdef __cplusplus /*...*/ #endif 和 extern "C" 的作用是防止 g++ 編譯器對“.c”文件用 C++ 的方式編譯,如果用 gcc 進行編譯,則直接寫 #include "called.h" 就行。
到此這篇關于C 與 C++ 接口函數相互調用的實現的文章就介紹到這了,更多相關C 與 C++ 接口函數調用內容請搜索億速云以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持億速云!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。