2010-10-10 17 views
1

J'essaie d'utiliser Microsoft Text Services Framework dans une application C#. Jusqu'ici, tout s'est bien passé, mais j'ai rencontré quelque chose qui m'a bloqué. Selon la documentation MSDN, l'interface ITfFnReconversion publie cette méthode:COM interop et marshaling d'un pointeur vers un pointeur vers une interface en C#

HRESULT GetReconversion(
    [in] ITfRange *pRange, 
    [out] ITfCandidateList **ppCandList 
); 

Que je l'ai déclaré en C# comme:

[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] 
void GetReconversion([In, MarshalAs(UnmanagedType.Interface)] ITfRange pRange, [Out, MarshalAs(UnmanagedType.Interface)] out ITfCandidateList ppCandList); 

Et je appelle comme ceci:

ITfCandidateList candidateList;  
reconversionInstance.GetReconversion(range, out candidateList); 

La valeur de reconversionInstance et la gamme ont été fixées plus tôt et je suis convaincu qu'ils sont valables. Chaque fois que cette ligne s'exécute, j'obtiens une erreur de violation d'accès indiquant que quelque chose a tenté de lire ou d'écrire de la mémoire protégée. Je suppose que cela est dû à un mauvais marshaling du paramètre candidateList, mais je suis ouvert à d'autres possibilités.

Étant donné que l'PARAM est déclarée comme un pointeur vers un pointeur, j'ai essayé aussi passer comme un IntPtr, comme ceci:

[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); 

Mais restait la même erreur.

Comment puis-je marshaler correctement afin que je puisse obtenir une instance de ITfCandidateList?

Pour plus de précisions, voici les interfaces que je les ai importé, mais comme je l'ai mentionné, je l'ai essayé quelques signatures différentes pour 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); 
} 

Répondre

0

Il y a quelque chose évidemment faux ici. ITfCandidateList **ppCandList ne peut pas traduire en une sortie simple: ceci est un pointeur vers un pointeur de ITfCandidateList.

À mon avis, vous devez définir que IntPtr et essayez de lire cette partie de la mémoire à l'aide Marshal.PtrToStructure.

+0

Merci pour l'entrée. J'ai essayé ceci, et il jette toujours la même erreur au sujet d'essayer de lire ou écrire la mémoire protégée. – Damion