C++ 用于Chrome的NPAPI插件不';无法通过NP\U初始化
我一直在尝试为Chrome编写一个使用NPAPI插件的扩展。我正在使用mingw来编译它。我最初努力让Chrome加载插件,但现在我遇到了一个不同的问题 我已经设法让Chrome调用NP_GetEntryPoints和NP_Initialize,但之后它就崩溃了。这是我到目前为止的代码 main.cpp:C++ 用于Chrome的NPAPI插件不';无法通过NP\U初始化,c++,windows,google-chrome-extension,npapi,C++,Windows,Google Chrome Extension,Npapi,我一直在尝试为Chrome编写一个使用NPAPI插件的扩展。我正在使用mingw来编译它。我最初努力让Chrome加载插件,但现在我遇到了一个不同的问题 我已经设法让Chrome调用NP_GetEntryPoints和NP_Initialize,但之后它就崩溃了。这是我到目前为止的代码 main.cpp: #include <iostream> #include <cstdlib> #include <Windows.h> #include <npapi
#include <iostream>
#include <cstdlib>
#include <Windows.h>
#include <npapi.h>
#include <npfunctions.h>
#define Exported extern "C" __declspec(dllexport)
NPNetscapeFuncs NPNFuncs;
Exported NPError NP_Initialize(NPNetscapeFuncs* pFuncs) {
if (pFuncs == NULL)
return NPERR_INVALID_FUNCTABLE_ERROR;
if (HIBYTE(pFuncs->version) > NP_VERSION_MAJOR)
return NPERR_INCOMPATIBLE_VERSION_ERROR;
if (pFuncs->size < sizeof(NPNetscapeFuncs))
return NPERR_INVALID_FUNCTABLE_ERROR;
// Save functions
NPNFuncs.size = pFuncs->size;
NPNFuncs.version = pFuncs->version;
NPNFuncs.geturlnotify = pFuncs->geturlnotify;
NPNFuncs.geturl = pFuncs->geturl;
NPNFuncs.posturlnotify = pFuncs->posturlnotify;
NPNFuncs.posturl = pFuncs->posturl;
NPNFuncs.requestread = pFuncs->requestread;
NPNFuncs.newstream = pFuncs->newstream;
NPNFuncs.write = pFuncs->write;
NPNFuncs.destroystream = pFuncs->destroystream;
NPNFuncs.status = pFuncs->status;
NPNFuncs.uagent = pFuncs->uagent;
NPNFuncs.memalloc = pFuncs->memalloc;
NPNFuncs.memfree = pFuncs->memfree;
NPNFuncs.memflush = pFuncs->memflush;
NPNFuncs.reloadplugins = pFuncs->reloadplugins;
NPNFuncs.getJavaEnv = pFuncs->getJavaEnv;
NPNFuncs.getJavaPeer = pFuncs->getJavaPeer;
NPNFuncs.getvalue = pFuncs->getvalue;
NPNFuncs.setvalue = pFuncs->setvalue;
NPNFuncs.invalidaterect = pFuncs->invalidaterect;
NPNFuncs.invalidateregion = pFuncs->invalidateregion;
NPNFuncs.forceredraw = pFuncs->forceredraw;*/
// Success
MessageBoxA(0, "NP_Initialize", "Log", 0);
return NPERR_NO_ERROR;
}
Exported void NP_Shutdown() {
MessageBoxA(0, "NP_Shutdown", "Log", 0);
}
/* Entry points */
NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData* savedData) {
MessageBoxA(0, "NPP_New", "Log", 0);
return NPERR_NO_ERROR;
}
NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value) {
MessageBoxA(0, "NPP_GetValue", "Log", 0);
return NPERR_NO_ERROR;
}
/*** Omitted... All the other functions are here, with just a MessageBox call in them ***/
Exported NPError NP_GetEntryPoints(NPPluginFuncs* pFuncs) {
if (pFuncs == NULL)
return NPERR_INVALID_FUNCTABLE_ERROR;
if (pFuncs->size < sizeof(NPPluginFuncs))
return NPERR_INVALID_FUNCTABLE_ERROR;
pFuncs->size = sizeof(NPPluginFuncs);
pFuncs->version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR;
pFuncs->newp = &NPP_New;
pFuncs->destroy = &NPP_Destroy;
pFuncs->setwindow = &NPP_SetWindow;
pFuncs->newstream = &NPP_NewStream;
pFuncs->destroystream = &NPP_DestroyStream;
pFuncs->asfile = &NPP_StreamAsFile;
pFuncs->writeready = &NPP_WriteReady;
pFuncs->write = &NPP_Write;
pFuncs->print = &NPP_Print;
pFuncs->event = &NPP_HandleEvent;
pFuncs->urlnotify = &NPP_URLNotify;
pFuncs->getvalue = &NPP_GetValue;
pFuncs->setvalue = &NPP_SetValue;
pFuncs->javaClass = NULL;
pFuncs->gotfocus = &NPP_GotFocus;
pFuncs->lostfocus = &NPP_LostFocus;
pFuncs->urlredirectnotify = &NPP_URLRedirectNotify;
pFuncs->clearsitedata = &NPP_ClearSiteData;
pFuncs->getsiteswithdata = &NPP_GetSitesWithData;
MessageBoxA(0, "NP_GetEntryPoints", "Log", 0);
return NPERR_NO_ERROR;
}
及
然后我链接到一个.DLL,其中包含:
g++.exe -Wl,--subsystem,windows -o "npplugin.dll" -s -shared main.o resource.o -lcomctl32 -lws2_32 -luxtheme -lgdi32 -lshell32 -lshlwapi
我建议使用某种形式的日志记录,而不是MessageBox;你有没有试过移除被点击的消息框,看看你是否能做得更好?Chrome会在进程之外启动插件,因此它希望这些入口点能够及时完成,否则它可能会杀死插件
此外,--plugin startup对话框选项在某些情况下可能非常有用,以便您可以确定插件何时启动;此外,如果您想附加一个调试器并查看是否可以通过这种方式找到更多信息,那么它可能会很有用。仅供参考。我也会尝试在firefox中加载它;有时,在另一个浏览器中加载插件会提供不同的信息。如果它在其中一种情况下有效,而在另一种情况下无效,那么也可以告诉您一些情况。mm尝试在
NP\u GetEntryPoints()中进行更改。
(……)
到
功能表之间的大小因浏览器和浏览器版本而异 根据硬编译的库标题检查大小:
if (pFuncs->size < sizeof(NPNetscapeFuncs))
return NPERR_INVALID_FUNCTABLE_ERROR;
Chrome发送一个80字节的结构
所以我猜最后一个函数指针不在chrome使用的结构中。有一点,尽管我怀疑这是问题所在,那就是这些都应该是&NPP_New,等等;在这种情况下,&运算符在某些编译器中是可选的,但为了正确起见,您应该使用它。@Taxilian谢谢,我已经忘记了这一点。不幸的是,它对崩溃没有帮助:(.您导出的函数可能需要是u stdcall。@Luke是的,它在
npfunctions.h
中的声明中设置。我在正确导出它们时遇到了一些问题,但我已经修复了…是吗?我很确定您需要包含(相同的)在函数声明和定义中调用约定。由于您的定义不包含约定,而且(可能)编译器也不会对此抱怨,我不确定。从我所能告诉您的情况来看,npfunctions.h似乎是一个标准头文件,它只定义函数签名,而不实际声明任何函数(除非您的修改)因此,这里指定的任何调用约定都不会应用于您的函数。我删除了所有的MessageBox,但发生了完全相同的事情。我还尝试了--plugin启动对话框,它弹出了一个带有进程ID的窗口。不过,我对mingw有点陌生,那么我该如何附加调试器呢?还有,我应该将我的npplugin.dll放在哪里才能获得Firefox找到它?我正在使用manifest.json让Chrome加载它…我不知道;我使用visual studio在windows上构建插件,因为它更易于使用。你也可以查看FireBreath(FireBreath.org)免责声明:我编写了FireBreath。稍后,我将尝试gdb
,看看问题出在哪里。我想了解NPAPI和NPRuntime,这就是为什么我决定不使用FireBreath的原因,但如果我无法使用它,我将开始使用它。您粘贴了NPPluginFuncs,而您可能是有意的要粘贴NPNetscapeFuncs,只需提醒一下。对任何感兴趣的人来说,它们都在npapi sdk的npfunctions.h中
g++.exe -Wl,--subsystem,windows -o "npplugin.dll" -s -shared main.o resource.o -lcomctl32 -lws2_32 -luxtheme -lgdi32 -lshell32 -lshlwapi
pFuncs->newp = &NPP_New;
pFuncs->destroy = &NPP_Destroy;
pFuncs->newp = NPP_New;
pFuncs->destroy = NPP_Destroy;
if (pFuncs->size < sizeof(NPNetscapeFuncs))
return NPERR_INVALID_FUNCTABLE_ERROR;
typedef struct _NPPluginFuncs {
uint16_t size;
uint16_t version;
NPP_NewProcPtr newp;
NPP_DestroyProcPtr destroy;
NPP_SetWindowProcPtr setwindow;
NPP_NewStreamProcPtr newstream;
NPP_DestroyStreamProcPtr destroystream;
NPP_StreamAsFileProcPtr asfile;
NPP_WriteReadyProcPtr writeready;
NPP_WriteProcPtr write;
NPP_PrintProcPtr print;
NPP_HandleEventProcPtr event;
NPP_URLNotifyProcPtr urlnotify;
void* javaClass;
NPP_GetValueProcPtr getvalue;
NPP_SetValueProcPtr setvalue;
NPP_GotFocusPtr gotfocus;
NPP_LostFocusPtr lostfocus;
NPP_URLRedirectNotifyPtr urlredirectnotify;
NPP_ClearSiteDataPtr clearsitedata;
NPP_GetSitesWithDataPtr getsiteswithdata;
NPP_DidCompositePtr didComposite;
} NPPluginFuncs;