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

MFC 專案呼叫 C# DLL 完整步驟:/clr 編譯、#using 導入、#pragma managed 混合模式

     編輯:關於C語言

前言

MFC (C++) 專案需呼叫 C# 組件,標準做法:將 MFC 專案設為 /clr (Common Language Runtime 支援),透過 #using 導入 .NET 組件,並在呼叫代碼前加 #pragma managed 進入 managed 區段。本文完整記錄 VS 專案屬性設定、代碼導入、混合模式編程三大步驟。

步驟一:MFC 專案啟用 /clr

  1. 右鍵專案 → Properties (屬性)
  2. Configuration Properties → General
    • Common Language Runtime Support:Common Language Runtime Support (/clr)
    • Use of MFC:Use MFC in a Shared DLL
  3. Configuration Properties → C/C++ → General
    • Debug Information Format:Program Database (/Zi) (非 /ZI)
  4. Configuration Properties → C/C++ → Code Generation
    • Runtime Library:Multi-threaded Debug DLL (/MDd) 或 Multi-threaded DLL (/MD)

關鍵:/clr 必須搭配 /MD 或 /MDd,否則連結錯誤。

步驟二:導入 .NET 組件與命名空間

// 標頭檔或 cpp 頂部
#using 
#using "YourCSharpAssembly.dll"  // 你的 C# DLL 路徑

using namespace System;
using namespace YourCSharpNamespace; // C# 類別所在命名空間

#using 會讀取組件中繼資料,產生 C++ 可呼叫的包裝類別。

步驟三:Managed/Unmanaged 邊界控制

void YourMfcFunction()
{
    // Unmanaged 代碼區...

    #pragma managed(push, on)  // 進入 Managed 區段
    {
        // 呼叫 C# 類別
        YourCSharpNamespace.YourClass^ obj = gcnew YourCSharpNamespace.YourClass();
        obj->YourMethod();
    }
    #pragma managed(pop)       // 返回 Unmanaged 區段

    // 繼續 Unmanaged 代碼...
}
  • #pragma managed(push, on):啟用 managed 編譯,允許使用 gcnew、^ 等 C++/CLI 語法
  • #pragma managed(pop):恢復 unmanaged 編譯
  • 也可對整個函數標記:#pragma managed 放在函數開頭

完整範例:MFC 按鈕事件呼叫 C# 服務

// MFC Dialog 類別
void CMfcDlg::OnBnClickedCallCSharp()
{
    #pragma managed
    {
        try
        {
            MyCSharpLib.Calculator^ calc = gcnew MyCSharpLib.Calculator();
            int result = calc->Add(10, 20);
            CString msg; msg.Format(_T("C# 回傳: %d"), result);
            AfxMessageBox(msg);
        }
        catch (System::Exception^ ex)
        {
            CString err; err.Format(_T("C# 例外: %s"), gcnew CString(ex->Message));
            AfxMessageBox(err);
        }
    }
}

常見坑與解決方案

替代方案對比

問題原因解決
連結錯誤 LNK2028Runtime Library 不匹配統一專案與所有靜態庫為 /MD 或 /MDd
載入 DLL 失敗C# DLL 依賴未複製到輸出目錄設定 C# 專案「複製到輸出目錄」或手動複製
呼叫例外 System.IO.FileNotFoundException組件解析路徑錯誤在 App.config 加 <probing privatePath="..\ManagedLibs\" />
Debug 斷點不生效/Zi vs /ZI、PDB 不匹配確保 C++ 專案用 /Zi,C# 專案產生 PDB (Debug 模式)
記憶體洩漏未正確釋放 COM/CLR 物件使用 gcroot<T>、auto_gcroot 或手動 delete (針對 native 指標)

總結

MFC 呼叫 C# DLL 的標準路徑:專案 /clr + /MD → #using 導入組件 → #pragma managed 邊界控制 → gcnew/^ 呼叫。關鍵在於 Runtime Library 一致性與 Managed/Unmanaged 邊界的精確劃分。新架構建議考慮 C++/CLI Wrapper 隔離層或進程間通訊,降低耦合與部署風險。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
方案優點缺點適用場景
/clr + #using (本文)強型別、IntelliSense、例外互通、效能佳需編譯為 mixed mode、部署複雜度稍高核心邏輯深度整合
COM Interop (CCW)純 Unmanaged C++、無 /clr需註冊、介面定義繁瑣、效能較差舊專案無法改 /clr
C++/CLI Wrapper DLL隔離 mixed mode、提供純 C 介面給 MFC多一層專案大型團隊、架構分層
Named Pipe / TCP / gRPC進程隔離、跨語言、可獨立部署序列化開銷、延遲、複雜度高微服務、跨機器