c與c 相互呼叫機制分析與實現

2021-09-07 04:17:19 字數 3279 閱讀 2477

c++通常被稱為better c,多數是因為c++程式可以很簡單的呼叫c函式,語法上基本實現相容。最常用的呼叫方式就是c++模組呼叫c實現的dll匯出函式,很簡單的用法,使用extern "c"將c標頭檔案或者函式修飾下。

本文主要涉及到在c模組中如何呼叫c++函式,或者換個名字,extern "c"在c語言中的功能介紹

通常,我們在需要呼叫c函式或者c實現的模組時,需要使用extern "c"修飾下對應的部分**,告訴c++編譯器按照c的呼叫規約呼叫相關模組**。常見的形式如下:

extern "c"

近期在看jni的呼叫實現機制,不自覺的在想c能呼叫c++模組嗎?

基本的思路是來在於c++語言提供的extern "c"機制,既然可以在c++中寫c模組,ok,那只需要乙個中間層就可以讓c呼叫c++的模組。

在c++實現如下函式:

// in header file(.h)

extern "c" int funcppdecorate(int param);

// in implenmentation file(.cpp)

int funcppdecorate(int param)

在c中按照下面方式呼叫

// declaration

int funcppdecorate(int param);

// invoke

funcppdecorate(1);

由於c不支援過載函式,如果需要c呼叫c++過載函式需要顯式的給出呼叫的方式,並在c宣告時給出對應對應機制。

在c++實現如下函式:

// in header file(.h)

void overloadfunc(int param, bool is_c=false);

void overloadfunc(double param, bool is_c=false);

extern "c"

// in implenmentation file(.cpp)

// ...

void overloaddecorate_i(int param)

void overloaddecorate_d(double param)

在c中按照下面方式呼叫

// declaration

void overloaddecorate_i(int param);

void overloaddecorate_d(double param);

// invoke

overloaddecorate_i(1);

overloaddecorate_d(2.0);

由於c++中類具有特殊的編譯器附加的構造和析構函式,為了在c中可以訪問c++的類,需要做一些c++編譯器實現的功能,比如物件的構造和析構。c不能直接使用class名稱,需要使用struct作為中轉。實現呼叫如下:

// in header file(.h)

class atype

;extern "c"

// in implenmentation file(.cpp)

// ...

extern "c" struct tagatype

;struct tagatype * createinstance()

void destoryinstance(struct tagatype ** atype)

}void classmemfunc(struct tagatype * pthis, int param)

在c中按照下面方式呼叫

// declaration

struct tagatype;

struct tagatype * createinstance();

void destoryinstance(struct tagatype ** atype);

void classmemfunc(struct tagatype * pthis, int param);

// invoke

struct tagatype * obj = createinstance();

classmemfunc(obj, 12);

destoryinstance(&obj);

g++ -c 1-c-invoke-cpp.cpp

gcc -c 1-c-invoke-cpp-main.c

gcc 1-c-invoke-cpp.o 1-c-invoke-cpp-main.o -o invoke.exe

invoke

pause

針對c++實現中的extern "c"修飾符的作用,可以使用nm命令檢視.o檔案的輸出格式,這是我使用gcc編譯後的輸出

nm 1-c-invoke-cpp.o

...00000000000000ac t _z12overloadfuncdb

0000000000000041 t _z12overloadfuncib

0000000000000000 t _z6printfpkcz

0000000000000000 t _z8denyfuncv

0000000000000168 t _zn5atype7memfuncei

0000000000000150 t _zn5atypec1ev

0000000000000150 t _zn5atypec2ev

000000000000015c t _zn5atyped1ev

000000000000015c t _zn5atyped2ev

00000000000001e4 t classmemfunc

000000000000018f t createinstance

00000000000001a7 t destoryinstance

u free

000000000000001b t funcppdecorate

u malloc

000000000000012c t overloaddecorate_d

000000000000008d t overloaddecorate_i

從上面輸出可以明顯看出c++和c的函式編譯之後的修飾規則是不同的。

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 模組使用。以下...