2010-10-12 27 views
1

Avant de poser ma question, je dois admettre que ma connaissance de .NET interop est clairsemée, donc je me rends compte que je pourrais faire une erreur de débutant.C# interop à XPCOM

J'utilise la bibliothèque GeckoFx pour créer une application C# qui contient une instance de navigateur Gecko (Firefox) intégrée. L'application fonctionne bien en utilisant GeckoFx dans sa forme originale, mais j'ai besoin de l'étendre pour prendre en charge les requêtes XPath, en utilisant l'interface Mozilla nsIDOMXPathEvaluator.

Le GeckoFx codebase comprend de nombreux exemples d'exposition et en utilisant les interfaces Gecko gérées sous-jacentes, et je l'ai suivi les mêmes modèles de code pour exposer plusieurs nouvelles interfaces:

[Guid("75506f8a-b504-11d5-a7f2-ca108ab8b6fc"), 
    ComImport, 
    InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
interface nsIDOMXPathEvaluator 
{ 
    nsIDOMXPathExpression CreateExpression(
     [MarshalAs(UnmanagedType.LPWStr)] string expression, 
     nsIDOMXPathNSResolver resolver); 

    nsIDOMXPathNSResolver CreateNSResolver(
     nsIDOMNode nodeResolver); 

    nsISupports Evaluate(
     [MarshalAs(UnmanagedType.LPWStr)] string expression, 
     nsIDOMNode contextNode, 
     nsIDOMXPathNSResolver resolver, 
     ushort type); 
} 

[Guid("ce600ca8-e98a-4419-ad61-2f6d0cb0ecc8"), 
    ComImport, 
    InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
interface nsIDOMXPathExpression 
{ 
    nsISupports Evaluate(
     nsIDOMNode contextNode, 
     ushort type, 
     nsISupports result); 
} 

[Guid("75506f83-b504-11d5-a7f2-ca108ab8b6fc"), 
    ComImport, 
    InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
interface nsIDOMXPathNSResolver 
{ 
    string LookupNamespaceUri(
     [MarshalAs(UnmanagedType.LPWStr)] string prefix); 
} 

Avec les nouvelles interfaces exposées, je tente de utiliser nsIDOMXPathEvaluator pour évaluer une expression XPath dans le contexte du DOM chargé:

var evaluator = Xpcom.CreateInstance<nsIDOMXPathEvaluator>("@mozilla.org/dom/xpath-evaluator;1"); 
var node = (nsIDOMNode)Document.DocumentElement.DomObject; 
var resolver = evaluator.CreateNSResolver(node); 
var result = evaluator.Evaluate("//div[0]", node, resolver, 0); 

Bien que les trois premières variables sont renseignées correctement, l'appel à Evaluate échoue avec un ex Ception "Tentative de lecture ou d'écriture de la mémoire protégée.". Je suis porté à croire que le problème réside dans la façon dont mon code marshals chaînes de valeurs, car j'ai vu différents messages d'exception lors de l'expérimentation avec le type marshalled du paramètre d'expression.

Il semble que je ne sois pas le seul à souffrir de ce problème, comme le montre this forum post, mais je ne comprends pas comment mon implémentation diffère des nombreux autres exemples de travail de la bibliothèque GeckoFx.

Toutes les idées seraient grandement appréciées.

Merci, Tim.

Répondre

2

Il y a 2 problèmes ici.

1) Il vous manque un argument dans la méthode nsIDOMXPathEvaluator.Evaluate. Vous avez besoin d'un argument nsISupports qui peut être utilisé pour collecter le résultat (en fait un nsIDOMXPathResult) si vous ne voulez pas créer un nouvel objet nsIDOMXPathResult.

2) Ces interfaces n'utilisent pas les chaînes normales que vous pouvez utiliser de cette façon. Si vous regardez la page de document pour nsIDOMXPathEvaluator par exemple, vous verrez qu'evaluation prend un DOMString plutôt qu'une chaîne ou un wstring. Dans GeckoFx, vous pouvez utiliser nsAString pour DOMString.

Alors nsIDOMXPathEvaluator.Evaluate ressemblera à ceci:

nsISupports Evaluate(
    nsAString expression, 
    nsIDOMNode contextNode, 
    nsIDOMXPathNSResolver resolver, 
    ushort type, nsISupports result); 

Et nsIDOMXPathNSResolver.LookupNamespaceUri ressemblera à ceci:

nsAString LookupNamespaceUri(nsAString prefix); 

Maintenant, vous devriez être en mesure de le faire:

var evaluator = Xpcom.CreateInstance<nsIDOMXPathEvaluator>("@mozilla.org/dom/xpath-evaluator;1"); 
var node = (nsIDOMNode)Document.DocumentElement.DomObject; 
var resolver = evaluator.CreateNSResolver(node); 
var result = evaluator.Evaluate(new nsAString(@"//div[0]"), node, resolver, 0, null); 

Et maintenant, vous ne devriez rencontrer aucune exception, et le résultat devrait être valide. Mais ce que vous faites avec le résultat sera une autre affaire. Vous aurez besoin de mettre en œuvre quelques autres interfaces pour en faire beaucoup usage, mais cela devrait vous mettre sur la bonne voie.

Salutations

+0

merci beaucoup - votre réponse est exacte.J'ai corrigé les deux erreurs dans mon code et ajouté la définition d'interface pour nsIDOMXPathResult et maintenant je suis capable de récupérer un résultat de noeud et de l'utiliser pour initialiser une nouvelle instance de GeckoNode. Merci encore. –