2010-12-14 53 views
0

Je suis en train d'étendre GeckoFx (http://geckofx.org) et j'ai quelques problèmes pour renvoyer des valeurs de tableau à partir d'interfaces non managées fournies par XPCom.Comment renvoyer correctement les valeurs de la méthode d'interface non managée?

J'ai ajouté une grande quantité de nouvelles fonctions à GeckoFx en utilisant la dernière version de XulRunner 1.9.2.13, mais je reçois des exceptions de violation d'accès lorsque je tente de renvoyer des tableaux à partir de méthodes d'interface. Par exemple:

[Guid("43987F7B-0FAA-4019-811E-42BECAC73FC5"), ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
interface mozISpellCheckingEngine 
{ 
    //... 
    void GetDictionaryList([MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPWStr)]ref string[] dictionaries, out uint count); 
    //... 
} 

public static string[] GetAvailableDictionaries() 
{ 
    string[] _dictionaries = null; 
    uint count = 0; 

    //GetSpellChecker() returns a valid mozISpellCheckingEngine object 
    GetSpellChecker().GetDictionaryList(ref _dictionaries, out count); 
    if (count > 0) 
    { 
     if (_dictionaries != null) 
     { 
      return _dictionaries; 
     } 
    } 
    return null; 
} 

Le problème est quand GetDictionaryList retourne parfois il retournera une liste avec un seul index et contenant le nom d'un dictionnaire (j'ai 2 dictionnaires à l'emplacement de cette méthode recherche dans) et compter les retours avec la valeur correcte de 2; d'autres fois la méthode échouera et lancera une violation d'accès et la valeur de _dictionaries est string [0] tandis que count reste correcte avec la valeur de 2.

Je suppose que la plus grande partie de cette question devrait être 'Suis-je marshaling la méthode et ses paramètres correctement dans la déclaration d'interface?

Cet exemple de code est juste que - un exemple. Il y a plusieurs autres fonctionnalités de XulRunner que je voudrais implémenter dans GeckoFx mais, elles retournent aussi des baies et souffrent du même problème. Jusqu'à ce que je puisse surmonter ce problème, mon travail est un peu à l'arrêt.

Merci pour toute l'aide que vous pouvez fournir.

-Scott

+0

Essayez de supprimer le mot-clé 'ref' de l'argument array, car cela implique un pointeur vers pointer-to-data (les tableaux sont implicitement des pointeurs en C#), et je suppose que l'interface spécifie pointer-to-data est commun pour les tableaux C). – cdhowie

+0

avez-vous eu accès au code de gestion pour l'éditer? –

Répondre

0

Change:

void GetDictionaryList([MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPWStr)]ref string[] dictionaries, out uint count); 

à:

void GetDictionaryList(ref IntPtr dictionaries, out uint count); 

et de l'utiliser comme:

IntPtr dictionaries = IntPtr.Zero; 
int count; 

GetDictionaryList(ref dictionaries, count); 

// check dictionaries != IntPtr.Zero; and count > 0 

// dictionaries will be a IntPtr to array IntPtr (of size count) 

string vals = new string[count]; 

for(int i = 0; i < count; ++i) 
    vals[i] = Marshal.PtrToStringUni(Marshal.SizeOf(typeof(IntPtr)) * i); 

(je ne l'ai pas compilé ce code de sorte qu'il peut être des fautes de frappe.)

+0

En fait, j'ai répondu à la question moi-même plusieurs minutes après l'avoir posté .. La réponse fournie ci-dessus est assez proche de ce que j'ai fini avec. – Scott