C# 与 XPCOM 的互操作

发布于 2024-09-27 06:36:31 字数 2117 浏览 6 评论 0原文

在提出我的问题之前,我应该承认我对 .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 的调用失败,并出现异常“尝试读取或写入受保护的内存。”。我倾向于认为问题在于我的代码封送字符串值的方式,因为我在尝试表达式参数的封送类型时看到了不同的异常消息。

看来我不是唯一遇到这个问题的人,如此论坛帖子所示,但我无法理解我的实现与 GeckoFx 库中​​的许多其他工作示例有何不同。

任何想法将不胜感激。

谢谢, 蒂姆.

Before asking my question, I should admit that my knowledge of .NET interop is sparse, so I realize that I might be making a newbie error.

I am using the GeckoFx library to create a C# application that contains an embedded Gecko (Firefox) browser instance. The app works well using GeckoFx in its original form, but I need to extend it to support XPath queries, using the Mozilla nsIDOMXPathEvaluator interface.

The GeckoFx codebase includes numerous examples of exposing and using the underlying managed Gecko interfaces, and I have followed the same code patterns to expose several new 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);
}

With the new interfaces exposed, I attempt to use nsIDOMXPathEvaluator to evaluate an XPath expression in the context of the loaded DOM:

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

Although the first three variables are correctly populated, the call to Evaluate fails with an exception "Attempted to read or write protected memory.". I am inclined to believe that the problem lies in the way my code marshals string values, as I have seen different exception messages when experimenting with the marshalled type of the expression parameter.

It seems that I am not the only person suffering this problem, as shown in this forum post, but I cannot understand how my implementation differs from the many other working examples in the GeckoFx library.

Any ideas would be greatly appreciated.

Thanks,
Tim.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

吐个泡泡 2024-10-04 06:36:31

这里有两个问题。

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

2) 这些接口不使用可以通过这种方式编组的普通字符串。例如,如果您查看 nsIDOMXPathEvaluator 的文档页面,您会发现评估需要一个 DOMString 而不是比 string 或 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);

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

干杯

There are 2 issues here.

1) You're missing an argument in the nsIDOMXPathEvaluator.Evaluate method. You need an nsISupports argument that can be used to collect the result (actually an nsIDOMXPathResult ) if you do not want to create a new nsIDOMXPathResult object.

2) These interfaces don't use normal strings that you can marshal that way. If you look at the document page for nsIDOMXPathEvaluator for instance, you will see that evaluate takes a DOMString rather than string or wstring. In GeckoFx you can use nsAString for DOMString.

So nsIDOMXPathEvaluator.Evaluate will look like this:

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

And nsIDOMXPathNSResolver.LookupNamespaceUri will look like this:

nsAString LookupNamespaceUri( nsAString prefix );

Now you should be able to do this:

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

And now you should not experience any exceptions, and result should be valid. But what you do with result will be another matter. You'll need to implement a few other interfaces to make much use of it, but that should get you on the right path.

Cheers

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文