Linux下C調用C++接口詳解
C++做久了,經常用C++的方式去思考問題,有時候就突然發現自己不太會寫C程序了。寫程序的時候,難免會用到第三方插件或者是庫,而這些插件或者庫很多時候都不能完全滿足我們的需求,遇到這種情況,如果全是C++,那好辦,寫個適配器就OK了,關於適配器模式參考我的博客《C++ Adaptor 設計模式》 如果要提供給C程序使用,那就需要自己封裝C程序可以使用的庫。前幾天在CSDN Linux/Unix版閑逛的時候,遇到一位網友,他問這樣的問題:(原話我記不住了,大致是這個意思)我要要封裝一個C++接口提供給C程序使用,C++程序完全沒有問題,可以運行,但是封裝的時候,我使用g++編譯,就沒問題,但是預期的結果是使用gcc編譯程序,可是使用gcc編譯的時候確保錯,很多 undefined...我想熟悉Linux編程的人一看這個問題都知道是怎麼回事。這裏我就不標新立異了,我隻想總結下如果讓C調用C++接口
再將接口封裝之前先將建C/C++的一些特性有助於後麵的理解。
C++創始人在編寫C++的時候,C語言正盛行,他不得不讓C++兼容C。C++最大的特性就是封裝,繼承,多態,重載。而這些特性恰恰是C語言所不具備的。至於多態,核心技術是通過虛函數表實現的,其實也就是指針。而對於重載,與C語言相比,其實就是編譯方式不同而已: C++編譯方式和C編譯方式。對於函數調用,編譯器隻要知道函數的參數類型和返回值以及函數名就可以進行編譯連接。那麼為了讓C調用C++接口或者是說C++調用C接口,就必須是調用者和被調用者有著同樣的編譯方式。這既是extern "C"的作用,extern “C”是的程序按照C的方式編譯。我們先來看看C++和C兩種編譯方式對於究竟有何不同,由於C隻考慮函數調用,這裏隻討論函數的差別。下來看一段源代碼:
我們用一個很簡短的代碼說明問題:
//cplus.cpp //按照C++方式編譯程序 int Operation(int)
鍵入命令編譯cplus: g++ -c cplus.cpp -o cplus.o 產生了目標文件cplus.o。我們來看看該目標文件中的符號
使用nm命令查看內部符號:nm cplus.o
內容很簡單:00000000 T _Z9Operationi
再來看看加 exern "C"按照C方式編譯程序:
extern "C" int Operation(int)
同樣使用上麵的命令產生cplus.o。然後查看符號如下:
00000000 T Operation
對比下可以發現,使用C++方式編譯函數多了個_Z9前綴和i後綴,其中i指的是參數類型。這下明白了,因為C不存在重載,隻需要知道函數名稱就可以確定函數,而C++有重載,需要根據參數類型和返回類型才可以唯一確定一個函數。
說道這裏,大家估計已經理解的差不多了。提供給C的接口必須加 extern "C"。這裏還隻是確定了編譯方式,extern "C"隻能讓編譯器安C的方式編譯。但是C並不認識
extern "C",這裏還要加一道工序:在C文件中 extern下接口。這樣C程序就認識接口函數了。下麵以一個簡單的例子來說明具體如何讓封裝C++接口給C使用。
//myclass.h #include <iostream> using namespace std; class Myclass { public: Myclass(){} ~Myclass(){} void Operation(); }; //myclass.cpp extern "C" void Myclass::Operation { cout << "Hi, Harlen" << endl; }
編譯命令:g++ -c myclass.cpp -o myclass.o
//interface.cpp #include "myclass.h" void interface() { Myclass obj; obj.Operation(); }
編譯命令:g++ -c interface.cpp -o interface.o
這樣,其實接口就已經準備好了。一種方式是使用命令:ar rs libinterface.a interface.o myclass.o產生靜態庫提供接口。
另一種方式是使用gcc,將調用程序的.o目標文件和myclass.o, interface.o一起編譯成可執行程序。
//main.c extern interface(); int main(int argc, char**argv) { interface() }
編譯:gcc -c main.c -o main.o
:gcc -o main interface.o myclass.o -lstdc++到此為止,接口已經提供完成。C程序中就可以使用interface接口了。
最後更新:2017-04-02 06:51:53