首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C 語言呼叫 C++ 函數完整指南:extern "C" 與動態連結庫實作

     編輯:關於C語言

方法一:動態連結庫(共享庫)

將 C++ 類別封裝於 extern "C" 函數中,編譯為 .so(Linux)或 .dll(Windows),C 程式透過 dlopen/dlsym(或 LoadLibrary/GetProcAddress)動態載入並呼叫。

// vector.cpp (C++)
extern "C" {
    void vector_add_string(char* str);
    void vector_list_strings(char* buff);
    std::vector<std::string> _stringList;
    void vector_add_string(char* str) { _stringList.push_back(str); }
    void vector_list_strings(char* buff) { /* 複製字串到 buff */ }
}
// 編譯:g++ -shared -o vector.so vector.cpp

// test.c (C)
void (*add)(char*); void (*list)(char*);
void* dp = dlopen("./vector.so", RTLD_LAZY);
add = dlsym(dp, "vector_add_string");
list = dlsym(dp, "vector_list_strings");

方法二:靜態連結與 extern "C" 包裝函數

直接在 C++ 原始碼中以 extern "C" 宣告非成員函數,提供 C 可呼叫的介面。若需呼叫成員函數(含虛擬函數),需撰寫包裝函數:

// C++ 程式碼
class C { virtual double f(int); };
extern "C" double call_C_f(C* p, int i) { return p->f(i); }

// C 程式碼
double call_C_f(struct C* p, int i); // 前向宣告
void ccc(struct C* p, int i) { double d = call_C_f(p, i); }

多載函數需提供不同名稱的包裝函數(如 f_i, f_d)。

類別物件跨語言傳遞

在共用標頭檔中定義對應的 C 結構體,確保記憶體配置相容:

// c.h
#ifdef __cplusplus
extern "C" {
#endif
typedef struct { int i; int j; } struct1; // 對應 class1 的資料成員
#ifdef __cplusplus
}
#endif

C++ 端以 reinterpret_cast 或 C 風格轉型將 struct1* 轉為 class1* 呼叫成員函數。

編譯與連結注意事項

  • C++ 原始檔用 g++ 編譯,C 原始檔用 gcc 編譯。
  • 連結時需連結 C++ 執行期庫(-lstdc++)。
  • Visual C++ 專案中,C 檔案需設定「不使用預編譯標頭」。

參考資源

Bjarne Stroustrup FAQ:Calling C++ from C

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved