MSDNCOMServer。MyCOMServer,介面 IMyCOMServer,方法 MyCOMServerMethod。wprintf(L"Inside MyCOMServerMethod")。CoInitialize(NULL); CoCreateInstance(CLSID_MyCOMServer, ..., IID_IMyCOMServer, (void**)&pUnk); pUnk->MyCOMServerMethod(); pUnk->Release(); CoUninitialize();
tlbimp MSDNCOMServer.dll
產生 MSDNCOMServerLib.dll,內含:
IMyCOMServer (保留 GUID、ComImport)。MyCOMServer 繼承 IMyCOMServer。MyCOMServerClass 實作上述兩介面,方法標記 MethodImplOptions.InternalCall。var com = new MyCOMServerClass(); com.MyCOMServerMethod();
編譯 csc /reference:MSDNCOMServerLib.dll ManagedClient.cs。
struct MyTestStruct { int nIndex; [string] WCHAR* sName; int nValue; };
HRESULT MyCOMServerMethod([in,out] BSTR* sTestString, MyTestStruct* pMyTestStruct);
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 端正確顯示。
.def 匯出 MyNonCOMMethod。[DllImport("MSDNCOMServer.dll")] static extern bool MyNonCOMMethod();。[ComVisible(true), Guid(...), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] interface IReversePInvoke { void ManagedMethod(ref int val); }。ManagedClass,修改參數值。tlbimp 產生的 Interop DLL 不含此介面,需用 tlbexp ManagedClient.exe 產生 .tlb,用 Oleview 取得 IDL 原型貼入 C++ 專案 IDL。MyNonCOMMethod(IReversePInvoke* ptr) 呼叫 ptr->ManagedMethod(¶m)。tlbimp 更新 Interop → 重新編譯 Managed 端。windbg ManagedClient.exe.symfix; .sympath+ https://msdl.microsoft.com/download/symbols; .reloadsxe ld mscorwks; sxe ld COMServerLib; sxe ld COMServerg,於載入 COMServer.dll 時中斷,下斷點 bp COMServer!CMyCOMServer::MyCOMServerMethod。.loadby sos mscorwks 載入 SOS。!bpmd ManagedClient ManagedClass.ManagedMethod。kL 檢視 CLRToCOMWorker、StubLinkStub 等轉換幀。!clrstack 顯示 ManagedClass.ManagedMethod、NDirectMethodFrameSlim (P/Invoke 轉換) 等。dv、dt 觀察參數值。