C呼叫C (C 封裝以及C對其呼叫)

2022-06-19 22:30:24 字數 3635 閱讀 7510

** 

相關知識提點:很經典的extern c解釋

編譯器:

gcc和g++編譯器區別

gcc是c語言編譯器(也可處理c++);g++是c++編譯器

g++對.c和.cpp檔案都當c++處理;gcc對.c檔案當作c處理,對.cpp當做c++處理

g++編譯器在使用時其實呼叫的是gcc編譯器

gcc不能自動鏈結庫檔案(.so等),一般用g++來自動鏈結庫檔案,要一定使用gcc則需要加上-lstdc++引數(使用libstdc++.so庫)

gcc編譯器和g++編譯器在編譯函式時,在相同呼叫方式下(如都是用_stdcall),對函式名的修飾方式不一樣

gcc和g++搜尋庫檔案的原則

標頭檔案如果放在/usr/include/下,庫檔案放在/lib或/usr/lib或usr/local/lib下編譯器會自動發現對應的庫

如果標頭檔案和庫檔案不在上述位置存放則在編譯器編譯時需要指定對應依賴的標頭檔案和庫檔案的位置,否則編譯器找不到庫檔案。指定方式:

使用-i(大寫的i)指定標頭檔案位置

使用-l指定庫檔案位置

使用 -l庫名 指定鏈結的庫名

例子(鏈結mytest/lib下的libgtd.so庫,注意使用-lgtd來指定):g++ test.cpp -o test.txt -l /mytest/lib -lgtd -i /mytest/include

函式名的修飾:

含義:函式的名字修飾(decorated name)就是編譯器在編譯期間建立的乙個字串,用來指明函式的定義或原型。link程式或其他工具有時需要指定函式的名字修飾來定位函式的正確位置。多數情況下程式設計師並不需要知道函式的名字修飾,link程式或其他工具會自動區分他們。當然,在某些情況下需要指定函式的名字修飾,例如在c++程式中, 為了讓link程式或其他工具能夠匹配到正確的函式名字,就必須為過載函式和一些特殊的函式(如建構函式和析構函式)指定名字裝飾。

幾種函式呼叫約定(__cdecl, __stdcall,__fastcall)

用法:呼叫約定說明符放在函式名前,如int __cdecal add(int a, int b);呼叫約定一定在函式的宣告和定義中都指定且需保持一致

幾種呼叫約定的區別

函式被呼叫時引數(尤其形參)的入棧順序不同

函式出棧是由呼叫函式還是由被調函式彈出棧的區別

函式名的修飾方式不同。函式名的修飾時編譯器在編譯函式時對函式名進行名稱修飾的操作。這對c語言和c++由很大不同,因為c++有同名函式的過載,類的構造和析構函式。

由於前兩種區別由編譯器決定,程式設計者無從干預,所以不再深究。那麼對於第三種(函式名的修飾)區別下面主要說明。

不同編譯環境(c和c++環境)下,各呼叫約定下對函式名修飾原則

如函式為:int functionname(int a, int b)

c環境下

__cdecl對函式名的修飾:__functionname

__stdcall對函式名的修飾:_functionname@number(number為形參的位元組數)

__fastcall對函式的修飾:@functionname@number(number為形參的位元組數)

c++環境下(為了過載、繼承特性)

以「?」標識函式名的開始,後跟函式名

如果是__cdecal呼叫約定,函式名後面接「@@ya」標識參數列的開始;如果是__stdcall呼叫約定,函式名後面接「@@yg」標識參數列的開始;如果是__fastcall呼叫約定,函式名後面接「@@yi」標識參數列的開始。

後面再跟參數列,參數列以代號表示(各代號的含義後面說明),參數列的第一項為該函式的返回值型別,其後依次為引數的資料型別,指標標識在其所指資料型別前;

參數列後以「@z」標識整個名字的結束,如果該函式無引數,則以「z」標識結束。

參數列代號說明

x--void , 

d--char,

e--unsigned char,

f--short,

h--int,

i--unsigned int,

j--long,

k--unsigned long,

m--float,

n--double,

_n--bool,

pa--指標,如果pa表示的是類物件的指標,則pa後接「v+類名+@@」

那麼上面的functionname函式在__cdecal呼叫約定下編譯出的函式名修飾為?add@@yahhh@z其餘不再列舉。

note: vs中編譯c++程式時,編譯器自動定義了乙個預處理名字__cplusplus,而編譯標準c時,自動定義名字__stdc__

linux下c呼叫c++庫(首先要對c++封裝成c)例項:

例項鏈結

例項說明:

生成的libadd.so、mylib.so、main.bin缺一不可(因為時動態庫),其中libadd.so是原始c++的實現庫,而mylib.so是c對c++封裝後的庫,main.bin是最終的可執行程式。

勘誤:mylib.so的編譯命令中-la 應為-ladd,即鏈結上libadd.so庫。

如果沒有按照例子中將libadd.so放到/usr/lib/下,則在編譯mylib.so庫時應該先指定動態庫環境變數ld_library_path的值(libadd.so的位置)。

** class

;#endif

#include ""0

) color) )

extern"c

";#endif

#endif

#include "

"#include ""

#ifdef __cplusplus

extern"c

";)color)

#ifdef __cplusplus

};#endif

3. test.c

#include "

"#include

#include

#include

#include

int main(void

)

可以用 gcc編譯:

extern"c

";#endif

#endif

#include "

"#include ""

#include

#ifdef __cplusplus

extern"c

"void releaseinstance(int *handle)

void setcolor(int handle, int

color)

int getcolor(int

handle)

#ifdef __cplusplus

};#endif

test.c

#include "

"#include

#include

#include

#include

int main(void

)

***************=== end

C呼叫C (C 封裝以及C對其呼叫)

gcc和g 搜尋庫檔案的原則 例子 鏈結mytest lib下的libgtd.so庫,注意使用 lgtd來指定 g test.cpp o test.txt l mytest lib lgtd i mytest include 函式名的修飾 幾種函式呼叫約定 cdecl,stdcall,fastcal...

C和C 混編,c呼叫C ,c 呼叫C

這兩天一直在解決這樣的乙個問題,專案之中有如下的需求 嵌入式的產品,演算法部分用c 實現,而控制程式和其它程式用c實現.這就要求可以通過c來呼叫c 的演算法程式.同時,這個專案有乙個pc的demo程式,是用vc開發的,這又要求c 能呼叫c的主控程式.一直知道應該用extern,但是具體該如何使用,一...

c呼叫c c 呼叫c的混合程式設計

c與c 混合程式設計 1.c 調c c 呼叫c函式是最簡單的,直接調即可。在c.h標頭檔案,加巨集定義,告訴用gcc編譯就好。ifdef cplusplus extern c endif2.c呼叫c c呼叫c 函式,相對複雜。c 標頭檔案需要以下這麼做 作為中間的標頭檔案 ifdef cpluspl...