C代碼中如何調用C++ C++中如何調用C


注意這里的C調用C++或者C++調用C意思是.c文件中調用.cpp文件中代碼,或者相反。

集成開發環境如VC++6.0或者vs都是以文件后綴來區別當前要編譯的是C代碼還是C++代碼,然后采用響應的編譯、調用協議等。

使用extern "C" 主要是因為C編譯器編譯函數時不帶參數的類型信息,只包含函數的符號名字。如
int foo( float x )
C編譯器會將此函數編譯成類似_foo的符號,C連接器只要找到了調用函數的符號,就認為連接成功。
而C++編譯器為了實現函數重載,會在編譯時帶上函數的參數信息。如它可以把上面的函數編譯成類似於_foo_float這樣的符號。
所以,C調用C++,使用extern "C"則是告訴編譯器依照C的方式來編譯封裝接口,當然接口函數里面的C++語法還是按C++方式編譯。
如:1 普通函數
// C++ Code
extern "C" int foo( int x );
int foo( int x )
{
   //...
}
這樣,編譯器會將foo函數編譯成類似_foo符號,而不會編譯成類似_foo_int符號
則C可以這樣調用C++函數
// C Code
int foo( int x );
void cc( int x )
{
    foo( x );
    //...
}
2 如果想調用重載的C++函數,則須封裝單獨的接口共C調用。

// C++ Code
void foo( int x );
void foo( float x );

extern "C" void foo_i( int x )
{
    foo( x );
}
extern "C" void foo_f( float x )
{
    foo( x );
}搜索
則C中可這樣調用
// C Code
void foo_i( int x );
void foo_f( float x );
void ccc( int x1, float x2 )
{
    foo_i( x1 );
    foo_f( x2 );
    // ...
}
3 C中想調用C++中的成員函數(包括虛函數),則需要提供一個簡單的包裝(wrapper)。

例如: // C++ code:

class C

{

  ...

  virtual double f(int);

};

extern "C" double call_C_f(C* p, int i) // wrapper function

{

return p->f(i);

}

然后,你就可以這樣調用 C::f():

//C code

double call_C_f(struct C* p, int i);//聲明

void ccc(struct C* p, int i)

{

   double d=call_C_f(p,i);

 ...

}

問題:參數struct C* p從哪里來,即怎么在C中定義C++對象,其實上面只是說了思想,真實的c中使用C++類需要把原來的類都封裝一下,參看下面的文章

http://blog.csdn.net/caspiansea/article/details/9676153


而C++調用C,extern "C" 的作用是:讓C++連接器找調用函數的符號時采用C的方式 如:
// C Code
void foo( int x );

C++這樣調用C函數
// C++ Code
extern "C" void foo( int x );

就是讓C++連接器能過類似於_foo來查找此函數,而非類似於_foo_int這樣的符號。

 

時常在cpp的代碼之中看到這樣的代碼: 特別是C ++中引入C的頭文件,這些C頭文件中出現很多如下代碼。

#ifdef __cplusplus extern "C" { #endif

//一段代碼

#ifdef __cplusplus } #endif  

其中__cplusplus是C++編譯器的保留宏定義.就是說C++編譯器認為這個宏已經定義了.
所以關鍵是extern "C" {}
extern "C"是告訴C++編譯器件括號里的東東是按照C的obj文件格式編譯的,要連接的話按照C的命名規則去找.

  要明白為何使用extern "C",還得從cpp中對函數的重載處理開始說起。在c++中,為了支持重載機制,在編譯生成的匯編碼中,要對函數的名字進行一些處理,加入比如函數的返回類型等等.而在C中,只是簡單的函數名字而已,不會加入其他的信息.也就是說:C++和C對產生的函數名字的處理是不一樣的.

明白了加入與不加入extern "C"之后對函數名稱產生的影響,我們繼續我們的討論:為什么需要使用extern "C"呢?C++之父在設計C++之時,考慮到當時已經存在了大量的C代碼,為了支持原來的C代碼和已經寫好C庫,需要在C++中盡可能的支持C,而extern "C"就是其中的一個策略。

  試想這樣的情況:一個庫文件已經用C寫好了而且運行得很良好,這個時候我們需要使用這個庫文件,但是我們需要使用C++來寫這個新的代碼。如果這個代碼使用的是C++的方式鏈接這個C庫文件的話,那么就會出現鏈接錯誤.

現在我們有了一個C庫文件,它的頭文件是f.h,產生的lib文件是f.lib,那么我們如果要在C++中使用這個庫文件,我們需要這樣寫:

extern "C" {

#include "f.h"

}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM