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

C# 與原生 C++ 互操作(三):P/Invoke 進階與 C++ 類包裝器

     編輯:關於C語言

.NET 框架雖內建 `MessageBox`,但大量 Win32 API 需 P/Invoke 調用。本文深入探討 `DllImport` 修飾符、調用約定陷阱,並示範正確包裝 C++ 類的模式。

P/Invoke 關鍵細節

  • 句柄類型:務必用 `IntPtr` 對應 `HWND`/`HANDLE`,自動適配 32/64 位。
  • CharSet.Auto:根據目標 OS 自動選 Unicode/ANSI。
  • CallingConvention:默認 `Winapi`(Windows 上為 `StdCall`,CE 為 `CDecl`)。C++ 成員函數使用 `ThisCall`(ECX 傳 this),直接 P/Invoke 極易導致堆疊錯誤(如 `ESP not properly saved`)。

為何不直接 P/Invoke C++ 成員函數

  1. 調用約定不匹配(`StdCall` vs `ThisCall`)
  2. C++ 名稱修飾支援函數重載,需 `extern "C"` 抑制(但成員函數無法這樣做)
  3. 即使用完整修飾名與 `CallingConvention.ThisCall`,極不穩定、不可維護

正確做法:托管包裝器模式

public __gc class Widget {
private:
    CWidget* m_pObj; // 原生指標
public:
    Widget() { m_pObj = new CWidget; }
    ~Widget() { delete m_pObj; }
    int Method(int n) { return m_pObj->Method(n); }
    // 僅暴露需要的方法
};

包裝器標準流程

  1. 建立 `__gc` 托管類,持有原生類指標
  2. 建構子/解構子管理原生物件生命週期
  3. 編寫對應原生成員函數的包裝方法
  4. 可轉換為 .NET 風格屬性(如 `GetName`/`SetName` → `Name` 屬性)

互操作路徑總結

互操作路徑圖

  • 托管→非托管:P/Invoke(C 函數) / 包裝器(C++ 類)
  • 非托管→托管:Managed Extensions / C++/CLI
  • COM 互操作另闢專題
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved