[英]COM interop and marshaling of a pointer to a pointer to an interface in C#
我正在嘗試在C#應用程序中使用Microsoft的Text Services Framework。 到目前為止,一切都進行得很順利,但是我遇到了讓我感到困惑的事情。 根據MSDN文檔,ITfFnReconversion接口發布了此方法:
HRESULT GetReconversion(
[in] ITfRange *pRange,
[out] ITfCandidateList **ppCandList
);
我在C#中聲明為:
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void GetReconversion([In, MarshalAs(UnmanagedType.Interface)] ITfRange pRange, [Out, MarshalAs(UnmanagedType.Interface)] out ITfCandidateList ppCandList);
像這樣打電話:
ITfCandidateList candidateList;
reconversionInstance.GetReconversion(range, out candidateList);
reconversionInstance和range的值是較早設置的,我相信它們是有效的。 每次執行此行時,我都會收到一個訪問沖突錯誤,表明有人嘗試讀取或寫入受保護的內存。 我假設這是由於對候選人列表參數進行了不正確的封送處理,但是還有其他可能性。
鑒於已將參數聲明為指向指針的指針,我還嘗試將其作為IntPtr傳遞,如下所示:
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void GetReconversion([In, MarshalAs(UnmanagedType.Interface)] ITfRange pRange, [Out, MarshalAs(UnmanagedType.SysInt)] out IntPtr ppCandList);
IntPtr candidateList;
reconversionInstance.GetReconversion(range, out candidateList);
但是卻留下了同樣的錯誤。
我如何正確地將其編組,以便獲得ITfCandidateList的實例?
為了澄清起見,這是我導入它們時的接口,盡管如上所述,我為GetReconversion嘗試了一些不同的簽名:
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("4CEA93C0-0A58-11D3-8DF0-00105A2799B5")]
public interface ITfFnReconversion : ITfFunction
{
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void GetDisplayName([Out, MarshalAs(UnmanagedType.BStr)] out string pbstrName);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void QueryRange([In, MarshalAs(UnmanagedType.Interface)] ITfRange pRange, [In, Out, MarshalAs(UnmanagedType.Interface)] ref ITfRange ppNewRange, [Out, MarshalAs(UnmanagedType.Bool)] out bool pfConvertable);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void GetReconversion([In, MarshalAs(UnmanagedType.Interface)] ref ITfRange pRange, [Out, MarshalAs(UnmanagedType.SysInt)] out IntPtr ppCandList);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void Reconvert([In, MarshalAs(UnmanagedType.Interface)] ITfRange pRange);
}
[ComImport, Guid("A3AD50FB-9BDB-49E3-A843-6C76520FBF5D"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ITfCandidateList
{
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void EnumCandidates([Out, MarshalAs(UnmanagedType.Interface)] out IEnumTfCandidates ppEnum);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void GetCandidate([In] uint nIndex, [Out, MarshalAs(UnmanagedType.Interface)] out ITfCandidateString ppCand);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void GetCandidateNum([Out] out uint pnCnt);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void SetResult([In] uint nIndex, [In, ComAliasName("TSF.TfCandidateResult")] TfCandidateResult imcr);
}
這里顯然有問題。 ITfCandidateList **ppCandList
無法轉換為簡單輸出:這是指向ITfCandidateList
指針的指針。
我認為,您需要將其定義為IntPtr
,然后嘗試使用Marshal.PtrToStructure.
讀取內存的該部分Marshal.PtrToStructure.
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.