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

C++ 程序員如何向 Java 工程師解釋 extern "C" 的作用與原理

     編輯:關於C++

extern "C" 是 C++ 與 C 互操作的核心橋樑,指示編譯器對被修飾的函數/變量採用 C 語言鏈接約定(不進行 Name Mangling),使 C++ 代碼能正確調用 C 庫,或 C 代碼調用 C++ 導出符號。

一、為什麼需要 extern "C"?

1.1 C++ Name Mangling(名字修飾)

為了支持函數重載,C++ 編譯器將函數簽名編碼進符號名:

void foo(int x, int y);
// C 編譯器符號:_foo
// C++ 編譯器符號:_foo_int_int / ?foo@@YAXHH@Z (MSVC) 等

1.2 C 不修飾,直接用函數名

若 C++ 直接調用 C 庫導出的 foo,鏈接器會尋找修飾後的名字 → 找不到 → LNK2019。

二、extern "C" 的雙重含義

  1. extern:聲明符號具有外部鏈接,可跨編譯單元可見。
  2. "C":指定鏈接語言為 C,禁止 Name Mangling。

三、標準頭文件守護模式

#ifndef MY_HEADER_H
#define MY_HEADER_H

#ifdef __cplusplus
extern "C" {
#endif

// C 風格聲明
void c_api_init();
int c_api_compute(int a, int b);

#ifdef __cplusplus
}
#endif

#endif // MY_HEADER_H

四、實際場景:C++ 調用 C 編譯的 DLL

DLL 端(C 編譯)

// mylib.c
#include <windows.h>
#define EXPORT __declspec(dllexport)

EXPORT void hello() { MessageBox(NULL, "Hi from C DLL", "DLL", MB_OK); }

EXE 端(C++ 調用)

// main.cpp
extern "C" void hello(); // 告訴 C++ 編譯器:這個符號按 C 方式鏈接

int main() {
    HMODULE h = LoadLibrary("mylib.dll");
    auto fn = (void(*)())GetProcAddress(h, "hello"); // 符號名就是 "hello"
    fn();
    FreeLibrary(h);
}

五、語法變體

// 單個聲明
extern "C" void foo(int);

// 塊聲明
extern "C" {
    void bar(double);
    int  globalVar;
    #include "c_header.h" // 批量包含 C 頭文件
}

六、標準規定細節 (C++03 §7.5)

  • 只能出現在命名空間作用域(不能在類/函數內)。
  • 巢狀 extern "C" 以內層為準。
  • 類成員不能加 extern "C"。
  • 同一名字最多只能有一個 extern "C" 實體(跨命名空間也不行)。
  • extern "C" 強制外部鏈接,不能配合 static(但 static 在塊內合法,內部鏈接不產生語言鏈接)。

七、給 Java 開發者的類比

extern "C" 相當於 JNI 中的 native 關鍵字 + System.loadLibrary:告訴運行時「這個符號按 C ABI 查找,不要按 C++/Java 的名字規則找」。

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