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

CLR COM Interop 實戰入門:從 ATL 伺服器到雙向呼叫與混合除錯

     編輯:關於.NET

建立簡單 ATL COM 伺服器

  1. Visual C++ ATL 專案 MSDNCOMServer。
  2. 加入 ATL 簡單物件 MyCOMServer,介面 IMyCOMServer,方法 MyCOMServerMethod。
  3. 實作輸出 wprintf(L"Inside MyCOMServerMethod")。
  4. 編譯產生 DLL,IDL 定義 GUID、Type Library。

非管理代碼用戶端呼叫

CoInitialize(NULL);
CoCreateInstance(CLSID_MyCOMServer, ..., IID_IMyCOMServer, (void**)&pUnk);
pUnk->MyCOMServerMethod();
pUnk->Release(); CoUninitialize();

Tlbimp 轉換為 Managed Wrapper

tlbimp MSDNCOMServer.dll

產生 MSDNCOMServerLib.dll,內含:

  • 介面 IMyCOMServer (保留 GUID、ComImport)。
  • 類別介面 MyCOMServer 繼承 IMyCOMServer。
  • 實作類別 MyCOMServerClass 實作上述兩介面,方法標記 MethodImplOptions.InternalCall。

Managed 用戶端呼叫

var com = new MyCOMServerClass();
com.MyCOMServerMethod();

編譯 csc /reference:MSDNCOMServerLib.dll ManagedClient.cs。

封送複雜參數:字串與結構

IDL 修改

struct MyTestStruct { int nIndex; [string] WCHAR* sName; int nValue; };
HRESULT MyCOMServerMethod([in,out] BSTR* sTestString, MyTestStruct* pMyTestStruct);

Managed 端簽名 (Tlbimp 自動產生)

void MyCOMServerMethod([MarshalAs(UnmanagedType.BStr)] ref string sTestString, ref MyTestStruct pMyTestStruct);
  • BSTR* → ref string + MarshalAs(BStr)。
  • 結構內 WCHAR* → string + MarshalAs(LPWStr)。

伺服器端修改字串與結構內容

使用 SysFreeString/SysAllocString、CoTaskMemFree/CoTaskMemAlloc 管理非管理記憶體,修改後傳回 Managed 端正確顯示。

P/Invoke 呼叫非 COM 導出函數

  1. C++ 專案 .def 匯出 MyNonCOMMethod。
  2. Managed 端 [DllImport("MSDNCOMServer.dll")] static extern bool MyNonCOMMethod();。
  3. 呼叫成功,輸出非管理端列印訊息。

反向 P/Invoke:非管理代碼回呼 Managed 介面

  1. Managed 定義 [ComVisible(true), Guid(...), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] interface IReversePInvoke { void ManagedMethod(ref int val); }。
  2. 實作類別 ManagedClass,修改參數值。
  3. tlbimp 產生的 Interop DLL 不含此介面,需用 tlbexp ManagedClient.exe 產生 .tlb,用 Oleview 取得 IDL 原型貼入 C++ 專案 IDL。
  4. C++ 修改 MyNonCOMMethod(IReversePInvoke* ptr) 呼叫 ptr->ManagedMethod(¶m)。
  5. 重新編譯 C++ DLL → tlbimp 更新 Interop → 重新編譯 Managed 端。
  6. 執行結果:非管理端呼叫 Managed 方法,參數由 10 改為 20,雙向驗證成功。

混合模式除錯:WinDbg + SOS

  1. windbg ManagedClient.exe
  2. 設定符號伺服器:.symfix; .sympath+ https://msdl.microsoft.com/download/symbols; .reload
  3. 載入斷點:sxe ld mscorwks; sxe ld COMServerLib; sxe ld COMServer
  4. 執行 g,於載入 COMServer.dll 時中斷,下斷點 bp COMServer!CMyCOMServer::MyCOMServerMethod。
  5. .loadby sos mscorwks 載入 SOS。
  6. Managed 方法斷點:!bpmd ManagedClient ManagedClass.ManagedMethod。
  7. 非管理堆疊:kL 檢視 CLRToCOMWorker、StubLinkStub 等轉換幀。
  8. Managed 堆疊:!clrstack 顯示 ManagedClass.ManagedMethod、NDirectMethodFrameSlim (P/Invoke 轉換) 等。
  9. 變數檢視:dv、dt 觀察參數值。

關鍵工具連結

  • PInvoke.net:社群簽名庫。
  • Adam Nathan 《.NET and COM: The Complete Interoperability Guide》。
  • WinDbg 下載、SOS 參考文件。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved