C與C++接口相互調用


轉載於:http://blog.csdn.net/lincoln_2012/article/details/50801080   

  項目中經常使用C和C++混合編程,那么,在調用對方接口時,總是不可避免地出現問題。為了讓雙方和諧地工作,就得用到extern "C"。

1 問題

    在C++中,為了支持重載機制,在編譯時,要對函數的名字進行一些處理,比如加入函數的返回類型等來加以區別;在C中,只是簡單的函數名字而已。如函數void func(int i),C++會把它編譯成類似_fun_int或_xxx_funIxxx這樣的增加了參數類型的符號,這也是C++可以實現重載的原因;C則把該函數編譯成類似_fun的符號,C鏈接器只要找到該函數符號就可以鏈接成功,它假設參數類型信息是正確的。故而,關鍵問題是,C和C++在編譯時生成函數名字的方式是不同的。

2 方法

    extern "C"是C++的特性,是一種鏈接約定,它並不影響調用函數的定義,即使做了該聲明,對函數類型的檢查和參數轉換仍要遵循C++的標准,而不是C。主要是為了解決C++在調用C函數庫時,用C++直接鏈接就會出現不能識別符號的問題,而用上extern "C"后,告訴C++編譯器要以C語言的方式編譯和鏈接函數,即直接使用函數名而不是一個經過處理的函數名。

3 示例

3.1 C++中調用C接口

代碼:

  1. /***** C頭文件c.h *****/  
  2. #ifndef  _C_H_  
  3. #define _C_H_  
  4.   
  5. #ifdef __cplusplus    /*C++編譯器包含的宏,例如用g++編譯時,該宏就存在,則下面的語句extern "C"才會被執行*/  
  6. extern "C" {          /*C++編譯器才能支持,C編譯器不支持*/  
  7. #endif  
  8.   
  9. void C_fun();  
  10.   
  11. #ifdef __cplusplus  
  12. }  
  13. #endif  
  14.   
  15. #endif  
  1. /***** C源文件c.c *****/  
  2. #include "c.h"  
  3. void C_fun()  
  4. {  
  5.     /*dosomething*/  
  6. }  
  1. 功能:在文件cpp.cpp中調用文件c.c中的函數C_fun()  
  2. /****** C++源文件cpp.cpp ******/  
  3. #include "c.h"  
  4. int main()  
  5. {  
  6.      C_fun()  
  7. }  

編譯: g++ cpp.cpp c.c

3.2 C中調用C++接口

代碼:

  1. /**** C++頭文件 cpp.h *****/  
  2. #ifndef  CPP_H  
  3. #define CPP_H  
  4.   
  5. extern "C" int add( int x, int y );  
  6.   
  7. #endif  
  1. /**** C++源文件 cpp.cpp *****/  
  2. #include "cpp.h"  
  3. int add( int x, int y )  
  4. {  
  5.     return x + y;  
  6. }  
  1. 功能:C文件中調用C++的接口  
  2. /**** C源文件c.c *****/  
  3. extern int add( int x, int y );  
  4. int main( int argc, char* argv[])  
  5. {  
  6.       
  7. }  

編譯:gcc c.c cpp.cpp

3.3 C++中調用C庫的函數

代碼:

  1. /*C庫源文件: hello.c*/  
  2. #include <stdio.h>  
  3. void func()  
  4. {  
  5.     printf("hello,world!\n");  
  6. }  

編譯:gcc --shared -o libhello.so hello.c

  1. /*C++源文件test.cpp中調用C庫的函數*/  
  2. #include <iostream>  
  3.   
  4. #ifdef __cplusplus  
  5. extern "C" {               // 告訴編譯器下列代碼要以C鏈接約定的模式進行鏈接  
  6. #endif  
  7.   
  8. void func();  
  9.   
  10. #ifdef __cplusplus  
  11. }  
  12. #endif  
  13.   
  14. int main()  
  15. {  
  16.     func();  
  17.   
  18.     return 0;  
  19. }  

編譯:g++ test.cpp -o test -lhello

3.4 C中調用C++庫的函數

1)C++庫代碼

  1. /*C++庫源文件hello.cpp*/  
  2. #include <iostream>  
  3.   
  4. void funcpp()  
  5. {  
  6.   std::cout << "hello, world" << std::endl;  
  7. }  

編譯:g++ --shared -o libhello.so hello.cpp
2)中間接口庫,對C++庫進行二次封裝

  1. /*中間接口庫 mid.cpp*/  
  2. #include <iostream>  
  3.   
  4. void funcpp();  
  5.   
  6. #ifdef __cplusplus  
  7. extern "C" {  // 即使這是一個C++程序,下列這個函數的實現也要以C約定的風格來搞!  
  8. #endif  
  9.   
  10. void m_funcpp()  
  11. {  
  12.     funcpp();  
  13. }  
  14.   
  15. #ifdef __cplusplus  
  16. }  
  17. #endi  

編譯:g++ --shared -o libmid.so mid.cpp -lhello
3)C通過鏈接二次接口庫調用C++庫

  1. /*C源文件test.c*/  
  2. #include <stdio.h>  
  3.   
  4. int main()  
  5. {  
  6.     m_funcpp();  
  7.   
  8.     return 0;  
  9. }  

編譯:gcc test.c -l mid -o test


免責聲明!

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



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