我一直在努力为使用NPAPI插件的Chrome编写扩展。 我正在使用mingw来编译它。 我最初努力让Chrome加载插件,但现在我有一个不同的问题。
我已经设法让Chrome调用NP_GetEntryPoints和NP_Initialize,但之后崩溃。 这是我的代码到目前为止…
main.cpp :
#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; }
我为每个函数添加了一个MessageBox调用,所以我可以看到是否正在调用正确的函数。 当我运行我的testing页面,这是一个带有<embed>
标签的空白页面时,我收到一条消息说NP_GetEntryPoints
,然后一个说NP_Initialize
,然后Chromepopup一个栏,说我的插件已经崩溃。 我认为问题出现在我的NP_GetEntryPoints
,但是我看不到它…有什么我做错了,或者忘记了吗?
我编译:
g++.exe -DWIN32 -D_WIN32 -D_WINDOWS -D_WIN32_WINNT=0x0600 -D_WIN32_IE=0x0600 -D_UNICODE -DUNICODE -static-libgcc -static-libstdc++ -c "main.cpp" -o main.o
和
windres.exe "resource.rc" "resource.o"
和我链接到一个.DLL与:
g++.exe -Wl,--subsystem,windows -o "npplugin.dll" -s -shared main.o resource.o -lcomctl32 -lws2_32 -luxtheme -lgdi32 -lshell32 -lshlwapi
功能表之间的大小在浏览器和浏览器版本之间是不同的。
你检查你的硬编译的库头的大小:
if (pFuncs->size < sizeof(NPNetscapeFuncs)) return NPERR_INVALID_FUNCTABLE_ERROR;
这可能是问题。 例如最新的(在编写gecko xulrunner SDK时包含一个84字节大小的struct:
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;
Chrome以80字节的结构发送。
所以我想最后一个函数指针不在chrome使用的结构中。
我会建议使用某种形式的日志而不是messageboxes; 你有没有尝试删除正在受到打击的消息框,看看你是否进一步? Chrome浏览器启动插件的过程,所以它会期望这些入口点及时完成,否则它可能会杀死插件。
另外,在某些情况下,–plugin-startup-dialog选项可能是有用的,所以你可以确定插件何时启动; 另外,如果你想附加一个调试器,看看你是否可以找到更多的信息,这可能是有用的。 只是一个供参考。 我也尝试加载它在Firefox中; 有时在另一个浏览器中加载插件会为您提供不同的信息。 如果它在一个而不是另一个中起作用,那也可以告诉你一些事情。
mm尝试在NP_GetEntryPoints()
更改
pFuncs->newp = &NPP_New; pFuncs->destroy = &NPP_Destroy;
(……)
至
pFuncs->newp = NPP_New; pFuncs->destroy = NPP_Destroy;