【问题标题】:C# interop to XPCOMC# 与 XPCOM 互操作
【发布时间】:2010-10-12 12:38:19
【问题描述】:

在问我的问题之前,我应该承认我对 .NET 互操作的了解很少,所以我意识到我可能会犯一个新手错误。

我正在使用GeckoFx 库创建一个包含嵌入式 Gecko (Firefox) 浏览器实例的 C# 应用程序。该应用程序使用原始形式的 GeckoFx 运行良好,但我需要使用 Mozilla nsIDOMXPathEvaluator 接口对其进行扩展以支持 XPath 查询。

GeckoFx 代码库包含大量公开和使用底层托管 Gecko 接口的示例,我遵循相同的代码模式公开了几个新接口:

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

随着新接口的暴露,我尝试使用 nsIDOMXPathEvaluator 在加载的 DOM 的上下文中评估 XPath 表达式:

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

虽然前三个变量已正确填充,但对Evaluate 的调用失败并出现异常“尝试读取或写入受保护的内存。”。我倾向于认为问题在于我的代码编组字符串值的方式,因为我在尝试使用表达式参数的编组类型时看到了不同的异常消息。

似乎我不是唯一遇到此问题的人,如 this forum post 所示,但我无法理解我的实现与 GeckoFx 库中​​的许多其他工作示例有何不同。

任何想法都将不胜感激。

谢谢, 蒂姆。

【问题讨论】:

    标签: c# interop marshalling xpcom geckofx


    【解决方案1】:

    这里有两个问题。

    1) 您在 nsIDOMXPathEvaluator.Evaluate 方法中缺少一个参数。如果您不想创建新的 nsIDOMXPathResult 对象,则需要一个可用于收集结果的 nsISupports 参数(实际上是一个 nsIDOMXPathResult )。

    2) 这些接口不使用您可以通过这种方式编组的普通字符串。例如,如果您查看 nsIDOMXPathEvaluator 的文档页面,您会看到评估采用 DOMString 而不是字符串或 wstring。在 GeckoFx 中,您可以将 nsAString 用于 DOMString。

    因此 nsIDOMXPathEvaluator.Evaluate 将如下所示:

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

    nsIDOMXPathNSResolver.LookupNamespaceUri 将如下所示:

    nsAString LookupNamespaceUri( nsAString prefix );
    

    现在你应该可以这样做了:

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

    现在您应该不会遇到任何异常,结果应该是有效的。但是你对结果做什么将是另一回事。您需要实现一些其他接口才能充分利用它,但这应该会让您走上正确的道路。

    干杯

    【讨论】:

    • 非常感谢 - 您的回答完全正确。我更正了代码中的两个错误并添加了 nsIDOMXPathResult 的接口定义,现在我能够检索节点结果并使用它来初始化新的 GeckoNode 实例。再次感谢。
    猜你喜欢
    • 2021-05-19
    • 1970-01-01
    • 1970-01-01
    • 2018-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-03
    • 2011-07-02
    相关资源
    最近更新 更多