【问题标题】:COM interop and marshaling of a pointer to a pointer to an interface in C#COM 互操作和封送指向 C# 中接口指针的指针
【发布时间】:2010-10-10 07:55:48
【问题描述】:

我正在尝试在 C# 应用程序中使用 Microsoft 的文本服务框架。到目前为止,一切都很顺利,但我遇到了让我难过的事情。根据 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);
}

【问题讨论】:

    标签: c# com interop marshalling


    【解决方案1】:

    这里有一些明显的错误。 ITfCandidateList **ppCandList 不能转换为简单的输出:这是指向 ITfCandidateList 的指针。

    在我看来,您需要将其定义为IntPtr,然后尝试使用Marshal.PtrToStructure. 读取那部分内存

    【讨论】:

    • 感谢您的意见。我已经尝试过了,它在尝试读取或写入受保护的内存时始终抛出相同的错误。
    猜你喜欢
    • 1970-01-01
    • 2012-08-28
    • 2017-06-21
    • 2021-08-14
    • 1970-01-01
    • 1970-01-01
    • 2017-11-06
    • 2021-12-31
    • 1970-01-01
    相关资源
    最近更新 更多