以下是假設舊的c程式庫
c的標頭檔案
/*-----------c.h--------------*/
#ifndef _c_h_
#define _c_h_
extern int add(int x, int y);
#endif
c的原始檔
/*-----------c.c--------------*/
int add(int x, int y)
c++的呼叫
/*-----------cpp.cpp--------------*/
#include "c.h"
void main()
這樣編譯會產生錯誤cpp.obj : error lnk2001: unresolved external symbol "int __cdecl add(int,int)" ([email=?add@@yahhh@z]?add@@yahhh@z[/email]),原因是找不到add的目標模組
這才令我想起c++過載的函式命名方式和c函式的命名方式,讓我們回顧一下:c中函式編譯後命名會在函式名前加以"_",比如add函式編譯成obj檔案時的實際命名為_add,而c++命名則不同,為了實現函式過載同樣的函式名add因引數的不同會被編譯成不同的名字
例如int add(int , int)==>add@@yahhh@z,
float add(float , float )==>add@@yammm@z,
以上是vc6的命名方式,不同的編譯器會不同,總之不同的引數同樣的函式名將編譯成不同目標名,以便於函式過載是呼叫具體的函式。
編譯cpp.cpp中編譯器在cpp檔案中發現add(1, 0);的呼叫而函式宣告為extern int add(int x, int y);編譯器就決定去找[email=add@@yahhh@z]add@@yahhh@z[/email],可惜他找不到,因為c的原始檔把extern int add(int x, int y);編譯成_add了;
為了解決這個問題c++採用了extern "c",這就是我們的主題,想要利用以前的c程式庫,那麼你就要學會它,我們可以看以下標準標頭檔案你會發現,很多標頭檔案都有以下的結構
#ifndef __h
#define __h
#ifdef __cplusplus
extern "c"
#endif
#endif /*__h*/
如果我們仿製該標頭檔案可以得到
#ifndef _c_h_
#define _c_h_
#ifdef __cplusplus
extern "c"
#endif
#endif /* _c_h_ */
這樣編譯
/*-----------c.c--------------*/
int add(int x, int y)
這時原始檔為*.c,__cplusplus沒有被定義,extern "c" {}這時沒有生效對於c他看到只是extern int add(int, int);
add函式編譯成_add(int, int);
而編譯c++原始檔
/*-----------cpp.cpp--------------*/
#include "c.h"
void main()
這時原始檔為*.cpp,__cplusplus被定義,對於c++他看到的是extern "c" 編譯器就會知道 add(1, 0);呼叫的c風格的函式,就會知道去c.obj中找_add(int, int)而不是[email=add@@yahhh@z]add@@yahhh@z[/email];
這也就為什麼dll中常看見extern "c" {},windows是採用c語言編制他首先要考慮到c可以正確呼叫這些dll,而使用者可能會使用c++而extern "c" {}就會發生作用
當原來的c語言寫的標頭檔案裡面沒有考慮這個問題的時候,可以寫成這樣:
#include
#include
extern "c"
這樣就可以在c++裡面用別人寫的c語言的東西了。
C呼叫C 鏈結庫
c呼叫c 鏈結庫 1.編寫c 編寫函式的時候,需要加入對c的介面,也就是extern c 2.由於c不能直接用 class.function 的形式呼叫函式,所以c 中需要為c寫乙個介面函式。例如本來要呼叫student類的talk函式,就另外寫乙個cfun 專門建乙個student類,並呼叫tal...
C 呼叫C鏈結庫
c 呼叫c鏈結庫 c 呼叫c語言的鏈結庫,其實相對c呼叫c 簡單。因為c 本來就向下相容c吧 個人見解 簡單說來原因就是未經處理的c 編譯後函式名可能變為 helloc 之類的,而c 編譯後函式名卻不是這樣,所以就對不上。詳細解釋見 需要在include c的檔案的時候加上extern c c.h ...
C 呼叫C 動態鏈結庫dll
在過程中發現兩種方法解決問題 一種是非託管c 建立的dll庫,需要用靜態方法呼叫。這種方法無法在c 的reference中直接引用,而是要用靜態呼叫的方法,其他部落格已經介紹的很詳盡,唯一需要補充的是,c 檔案需要先 usingsystem.runtime.interopservices 之後才可以...