【问题标题】:how can i talk with the C++ NPAPI dll in C#我如何在 C# 中与 C++ NPAPI dll 交谈
【发布时间】:2012-10-21 08:54:44
【问题描述】:

我有一个开源 C++ DLL

实际上它是来自 CRX 扩展的插件 dll,我试图在 Visual Studio 中使用 C# 调用它的函数

此扩展是 Google chrome-screen-capture

我设法创建了与 DLL 对话的代码,但我不知道如何调用它的函数。

这是我的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace ConsoleApplication1
{
    class Program
    {
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        private class Sample
        {
            public Int32 length;
            public String value;
        }

        [DllImport("C:\\Users\\Ofir\\Documents\\Visual Studio 2010\\Projects\\ConsoleApplication1\\ConsoleApplication1\\bin\\Debug\\screen_capture.dll")]
        private static extern void NP_Initialize();

        static void Main(string[] args)
        {
            Sample s = new Sample();
            s.length = 0;
            s.value = "Huhu";
            NP_Initialize(); <-- I get an ERROR here : 
        }
    }
}

错误:检测到 PInvokeStackImbalance 消息:对 PInvoke 的调用 功能 'ConsoleApplication1!ConsoleApplication1.Program::NP_Initialize' 有 堆栈不平衡。这可能是因为托管的 PInvoke 签名与非托管目标签名不匹配。检查 PInvoke 签名的调用约定和参数匹配 目标非托管签名。

我能做什么?

编辑:例如,如果我使用 NP_GetEntryPoints(),它将请求一个类型为 NPPluginFuncs 的指针。

例如:NPError WINAPI NP_GetEntryPoints(NPPluginFuncs* pFuncs)

这是它要求的类型:

typedef struct _NPPluginFuncs {
    uint16 size;
    uint16 version;
    NPP_NewUPP newp;
    NPP_DestroyUPP destroy;
    NPP_SetWindowUPP setwindow;
    NPP_NewStreamUPP newstream;
    NPP_DestroyStreamUPP destroystream;
    NPP_StreamAsFileUPP asfile;
    NPP_WriteReadyUPP writeready;
    NPP_WriteUPP write;
    NPP_PrintUPP print;
    NPP_HandleEventUPP event;
    NPP_URLNotifyUPP urlnotify;
    JRIGlobalRef javaClass;
    NPP_GetValueUPP getvalue;
    NPP_SetValueUPP setvalue;
} NPPluginFuncs;

但我不知道如何构建这种类型并发送它。 我想完成在 IE 工具栏中构建一个函数,然后使用这个 DLL 中的函数。 这样我就可以在 IE 中使用屏幕截图了。

EDIT2:当我调用 NP_Shutdown() 函数时,它就可以了。 一切都很清楚,没有例外。 所以我想这都是我发送给另一个函数的类型。 但是我怎么发送这种类型的呢?

【问题讨论】:

  • NP_Initialize 应该带参数吗? It looks like it,并且在期望它们时不传递它肯定会使堆栈失衡。您可以将CallingConvention 排除在您的DllImport 之外——这些函数被声明为WINAPI,这意味着默认调用约定很好,实际上使用Cdecl 会给您带来问题。
  • Ofear,如果你真的有no idea,那么最好的起点是the documentation on pinvoke marshalling。如果您需要特定部分的帮助,请更新您的问题。
  • 感谢您的 cmets,我的问题是制作这个 _NPPluginFuncs 对象并将其发送给函数...

标签: c# dllimport npapi


【解决方案1】:

这是一个老问题,但我最近对 ​​NPAPI 做了一些小旅行,所以我分享我的发现。虽然我无法测试你的情况,但我会走这条路。
首先声明一个_NPPluginFuncs结构:

[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct _NPPluginFuncs
{
    UInt16 size;
    UInt16 version;
    IntPtr newp;
    IntPtr destroy;
    IntPtr setwindow;
    IntPtr newstream;
    IntPtr destroystream;
    IntPtr asfile;
    IntPtr writeready;
    IntPtr write;
    IntPtr print;
    IntPtr @event;
    IntPtr urlnotify;
    IntPtr javaClass;
    IntPtr getvalue;
    IntPtr setvalue;
    IntPtr gotfocus;
    IntPtr lostfocus;
    IntPtr urlredirectnotify;
    IntPtr clearsitedata;
    IntPtr getsiteswithdata;
    IntPtr didComposite;
}

然后声明 PInvoke 调用:

[System.Runtime.InteropServices.DllImport("C:\\Users\\Ofir\\Documents\\Visual Studio 2010\\Projects\\ConsoleApplication1\\ConsoleApplication1\\bin\\Debug\\screen_capture.dll")]
private static extern void NP_Initialize(ref _NPPluginFuncs nPPluginFuncs);

[System.Runtime.InteropServices.DllImport("C:\\Users\\Ofir\\Documents\\Visual Studio 2010\\Projects\\ConsoleApplication1\\ConsoleApplication1\\bin\\Debug\\screen_capture.dll")]
private static extern IntPtr NP_GetEntryPoints(ref _NPPluginFuncs nPPluginFuncs);

[System.Runtime.InteropServices.DllImport("C:\\Users\\Ofir\\Documents\\Visual Studio 2010\\Projects\\ConsoleApplication1\\ConsoleApplication1\\bin\\Debug\\screen_capture.dll")]
private static extern void NP_Shutdown();

最后,调用 NPAPI:

_NPPluginFuncs nPPluginFuncs = new _NPPluginFuncs();
NP_Initialize(ref nPPluginFuncs);   // all members are 0 (IntPtr.Zero) after the call
IntPtr res = NP_GetEntryPoints(ref nPPluginFuncs);  // memory addresses filled in
NP_Shutdown();

您能否确认这是否适合您?你将面临另一项重大任务:调用NP_GetEntryPoints 返回的那些IntPtr 函数...

【讨论】:

  • 感谢 Peter Ivan 的回答。我会尝试确认这一点(这是我的一个旧项目。)但是你应该得到一些 +1 只是为了这个干净和有用的答案!
  • 嘿彼得。我遵循了这段代码并从 NP_GetEntryPoints 获得了指针。我该如何调用我的插件函数呢?
  • @Tsury:也许this SO question 可能会帮助你。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-11
  • 1970-01-01
  • 1970-01-01
  • 2010-10-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多