1

我有一个开源 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() 函数时,没关系。一切都很清楚,没有例外。所以我想这都是我发送给另一个函数的类型。但我将如何发送这种类型?

4

1 回答 1

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

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

于 2014-11-24T14:51:22.617 回答