C/C++混合編程

C中調用C++,C++中調用C都會用到extern "C",但兩者的意義卻大不一樣!!


先介紹在C++中調用C,這個大家都比較熟悉:

例:

//C代碼

  1. <span style="font-family:Microsoft YaHei;font-size:18px;">void foo( int x );  

  2. </span>  

<span style="font-family:Microsoft YaHei;font-size:18px;">void foo( int x );</span>

//C++代碼

  1. <span style="font-family:Microsoft YaHei;font-size:18px;">//C++ code 

  2. extern"C"void foo( int x );  

  3. </span>  

<span style="font-family:Microsoft YaHei;font-size:18px;">//C++ codeextern "C" void foo( int x );</span>讓C++連接器能通過過類似於_foo來查找此函數,而非類似於_foo_int這樣的符號。



使用extern "C"則是告訴編譯器依照C的方式來編譯封裝接口,當然接口函數裏面的C++語法還是按C++方式編譯。使用extern "C"則是告訴編譯器依照C的方式來編譯封裝接口,當然接口函數裏面的C++語法還是按C++方式編譯。


再來說說C中調用C++,這其中也會用到extern "C",這則是告訴編譯器依照C的方式來編譯封裝接口,當然接口函數裏面的C++語法還是按C++方式編譯。

C++代碼:(非成員函數)

  1. <span style="font-family:Microsoft YaHei;font-size:18px;">extern"C"int foo( int x );  

  2. int foo( int x )  

  3. {  

  4. //... 

  5. }</span>  

<span style="font-family:Microsoft YaHei;font-size:18px;">extern "C" int foo( int x );int foo( int x ){//...}</span>這樣,編譯器會將foo函數編譯成類似_foo符號,而不會編譯成類似_foo_int符號。


C代碼

 

  1. <span style="font-family:Microsoft YaHei;font-size:18px;">int foo( int x );  

  2. void cc( int x )  

  3. {  

  4.     foo( x );  

  5. //... 

  6. }</span>  

<span style="font-family:Microsoft YaHei;font-size:18px;">int foo( int x );void cc( int x ){foo( x );//...}</span>

 


如果你想要在 C 裏調用成員函數(包括虛函數),則需要提供一個簡單的包裝(wrapper)。例如:

 

  1. <span style="font-family:Microsoft YaHei;font-size:18px;">// C++ code: 

  2. class C  

  3. {  

  4. // ... 

  5. virtualdouble f(int);  

  6. };  

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

  8. {  

  9. return p->f(i);  

  10. }</span>  

<span style="font-family:Microsoft YaHei;font-size:18px;">// C++ code:class C{// ...virtual double f(int);};extern "C" double call_C_f(C* p, int i) // wrapper function{return p->f(i);}</span>
然後,你就可以這樣調用 C::f():

 

 

  1. <span style="font-family:Microsoft YaHei;font-size:18px;">/* C code: */

  2. double call_C_f(struct C* p, int i);  

  3. void ccc(struct C* p, int i)  

  4. {  

  5. double d = call_C_f(p,i);  

  6. /* ... */

  7. } </span>  

<span style="font-family:Microsoft YaHei;font-size:18px;">/* 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);/* ... */} </span>

 



如果你想在 C 裏調用重載函數,則必須提供不同名字的包裝,這樣才能被 C 代碼調用。例如:

 

  1. <span style="font-family:Microsoft YaHei;font-size:18px;">// C++ code: 

  2. void f(int);  

  3. void f(double);  

  4. extern"C"void f_i(int i) { f(i); }  

  5. extern"C"void f_d(double d) { f(d); } </span>  

<span style="font-family:Microsoft YaHei;font-size:18px;">// C++ code:void f(int);void f(double);extern "C" void f_i(int i) { f(i); }extern "C" void f_d(double d) { f(d); } </span>
然後,你可以這樣使用每個重載的 f():

 


  1. <span style="font-family:Microsoft YaHei;font-size:18px;">/* C code: */

  2. void f_i(int);  

  3. void f_d(double);  

  4. void cccc(int i,double d)  

  5. {  

  6.        f_i(i);  

  7.        f_d(d);  

  8. /* ... */

  9. } </span>  

<span style="font-family:Microsoft YaHei;font-size:18px;">/* C code: */void f_i(int);void f_d(double);void cccc(int i,double d){f_i(i);f_d(d);/* ... */} </span>

 


參考文獻:

Bjarne Stroustrup的原文鏈接地址是 http://www.research.att.com/~bs/bs_faq2.html#callCpp



下面就一個例子,來介紹一下C調用C++的過程:

 

  1. <span style="font-family:Microsoft YaHei;font-size:18px;">// cpp.h 

  2. #ifndef  __cpp_h__ 

  3. #define  __cpp_h__ 

  4. class  class1 {  

  5.     class1();  

  6.     ~class1();  

  7. public:  

  8. int  I;  

  9. int  J;  

  10. int  getI(void);  

  11. };  

  12. #endif 

  13. // end file 

  14. // cpp.cpp 

  15. #i nclude "stdafx.h"

  16. #i nclude  <iostream>  

  17. #i nclude  "cpp.h"

  18. #i nclude  "c.h"

  19. usingnamespace  std;       // 打開標準庫名字空間 

  20. class1::class1()  

  21. {}  

  22. class1::~class1()  

  23. {}  

  24. int  class1::getI(void)  

  25. {  

  26. return  I++;  

  27. }  

  28. // 按 C 調用方式編譯下面函數 

  29. extern"C"

  30. int  get_class1_I(struct1 * p)  

  31. {  

  32.     class1 * pClass1 = (class1 *)p;  

  33.     cout << "c++: " << pClass1->getI() << endl;  

  34. return  pClass1->getI();  

  35. }  

  36. // end file 

  37. // c.h 

  38. #ifndef  __c_h__ 

  39. #define  __c_h__ 

  40. #ifdef  __cplusplus 

  41. extern"C" {  

  42. #endif 

  43. typedefstruct {  

  44. int  i;             // 與 class1 類中變量一致 

  45. int  j;  

  46.     }struct1;  

  47. #ifdef  __cplusplus 

  48. }  

  49. #endif 

  50. #endif 

  51. // end file 

  52. // c.c 

  53. #i nclude  <cstdio>  

  54. #i nclude  "c.h"

  55. externint  get_class1_I(void * p);  

  56. struct1  s;  

  57. int  main(void)  

  58. {  

  59.     printf ("c: %d\n", get_class1_I(&s));  

  60.     printf ("c: %d\n", get_class1_I(&s));  

  61. return 0;  

  62. }  

  63. // end file</span>

<span style="font-family:Microsoft YaHei;font-size:18px;">// cpp.h#ifndef  __cpp_h__#define  __cpp_h__class  class1 {class1();~class1();public:int  I;int  J;int  getI(void);};#endif// end file// cpp.cpp#i nclude "stdafx.h"#i nclude  <iostream>#i nclude  "cpp.h"#i nclude  "c.h"using namespace  std;       // 打開標準庫名字空間class1::class1(){}class1::~class1(){}int  class1::getI(void){return  I++;}// 按 C 調用方式編譯下面函數extern "C"int  get_class1_I(struct1 * p){class1 * pClass1 = (class1 *)p;cout << "c++: " << pClass1->getI() << endl;return  pClass1->getI();}// end file// c.h#ifndef  __c_h__#define  __c_h__#ifdef  __cplusplusextern "C" {#endiftypedef struct {int  i;             // 與 class1 類中變量一致int  j;}struct1;#ifdef  __cplusplus}#endif#endif// end file// c.c#i nclude  <cstdio>#i nclude  "c.h"extern  int  get_class1_I(void * p);struct1  s;int  main(void){printf ("c: %d\n", get_class1_I(&s));printf ("c: %d\n", get_class1_I(&s));return 0;}// end file</span>在linux下,執行:

 

gcc -c c.c
g++ -c cpp.cpp
gcc -lstdc++ c.o cpp.o -o result

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章