核心演算法用 C++ (難逆向),其餘層 (UI、資料存取) 用 C#。上篇完成 C# 呼叫 C++ DLL,本篇完成 C++ 呼叫 C#,採 COM+ (ServicedComponent) 方案:C# 暴露 COM 介面,C++ 透過 `#import` 智慧指標呼叫。
[assembly: ComVisible(true)]
[assembly: Guid("94882155-3B7C-48e3-B357-234D56D8F15E")] // 類型庫 ID
using System;
using System.EnterpriseServices;
using System.Runtime.InteropServices;
namespace ComInteropDemo {
// 介面:需 Guid、DispId
[Guid("7103C10A-2072-49fc-AD61-475BEE1C5FBB")]
public interface IComInterop {
[DispId(1)] int Add(int a, int b);
[DispId(2)] int Minus(int a, int b);
}
// 實作:繼承 ServicedComponent、ClassInterfaceType.None
[Guid("87796E96-EC28-4570-90C3-A395F4F4A7D6")]
[ClassInterface(ClassInterfaceType.None)]
public class ComInterop : ServicedComponent, IComInterop {
public int Add(int a, int b) => a + b;
public int Minus(int a, int b) => a - b;
}
}
# 開發機命令列 (VS Developer Command Prompt)
regasm ComInteropDemo.dll /tlb:ComInteropDemo.tlb /codebase
# 重新編譯前需先解除註冊
regasm /u ComInteropDemo.dll
[DispId(N)]`,確保 vtable 位置固定。$(ProjectDir)..\ComInteropDemo\Debug` (含 .tlb)
#include "stdafx.h"
#include
using namespace std;
#import "..\\Debug\\ComInteropDemo.tlb" no_namespace named_guids
// 路徑依專案相對位置調整
int _tmain(int argc, _TCHAR* argv[]) {
HRESULT hr;
CoInitialize(NULL); // 初始化 COM 庫
// 建立介面智慧指標
ComInteropDemo::IComInteropPtr ptr;
// 建立 COM 物件實例
hr = ptr.CreateInstance(__uuidof(ComInteropDemo::ComInterop));
if (SUCCEEDED(hr)) {
cout << "Add(1,2) = " << ptr->Add(1, 2) << endl; // 輸出 3
} else {
cerr << "CreateInstance failed: 0x" << hex << hr << endl;
}
CoUninitialize(); // 釋放 COM
return 0;
}
COM+ 方案讓 C++ 以原生方式呼叫 C# 邏輯,適合「核心 C++、周邊 C#」架構。生產環境建議:介面版本管理、錯誤代碼標準化、效能基準測試 (COM 封送開銷)。