火狐NP插件開發 C++

 由於接觸NP插件的時間還是比較短,下面總結一下自己對NP插件的理解。

  NP插件還是對現有類的重載,然後實現自己想用的方法。在後面會具體的講怎麼用這樣的方法。

1、NP插件所要用到的官方的文件:

A、npapi.h

B、npfunctions.h

C、npruntime.h

D、nptypes.h

上面是幾個要用到的頭文件

A、np_entry.cpp

B、npn_gate.cpp

C、npp_gate.cpp

上面是要用到的源文件

2、下面說一下具體的創建dll的過程

A、開始創建工程


首先創建一個win32動態庫的空項目,如上圖所示。

B、然後將上面提到的所要用到的頭文件和源文件加入到工程中。我的工程的目錄如下 所示:


其中上面所提到的頭文件在include文件夾中。添加完成之後編譯一下代碼。這時候會 報找不到上面提到的頭文件錯誤這時候要設置頭文件的查找路徑,方法如下:


C/C++=〉常規=〉附加包含目錄,加入所要引用的頭文件的目錄。

再次編譯上面的代碼,你會發現不會報找不到上面提到的幾個頭文件。但是會包一個找 不到Plugin.h文件。在這裏Plugin.h文件並不是官方提供的,而是我們自己要添加的文 件。所以要添加plugin.h文件,方法如下:

一般情況下是添加一個類的形式添加頭文件和源文件,因爲在Plugin.h文件中必須實現 一個CPlugin的類。

添加這個類之後,還是會報很多的錯誤,這就是沒有添加自己要填寫的代碼的緣故。

Plugin.h文件中添加下面幾個頭文件的引用:

#include "npapi.h"

#include "npruntime.h"

#include <windef.h>

再編譯程序,你會發現程序的錯誤明顯的減少了,但是還是有錯誤,錯誤信息如下:

c:\program files (x86)\windows kits\8.1\include\um\winnt.h(147): fatal error C1189: #error :  "No Target Architecture"

通過查閱資料我發現編譯這個工程需要定義許多的宏定義,下面說一下需要添加什麼宏 定義。這時我在windows下定義的宏定義:(debug模式下)

_DEBUG

MOZILLA_STRICT_API

XP_WIN

WIN32

_WINDOWS

_X86_

_USRDLL

MYSECONDNP_EXPORTS

在如下圖所示的位置添加:


再重新編譯代碼還是報錯,是不是感覺錯誤太多了啊。我也不想再弄了。太麻煩,但是 要用,不弄還不行。硬着頭皮吧。

發現CPlugin類必須有一固定格式的構造函數,如下所示:

CPlugin(NPP pNPInstance);

修改之後編譯還是會報錯,經過錯誤信息判斷是CPlugin類中有好多的函數沒有實現所 導致的。

下面就添加這些函數,你會發現沒添加一個函數,錯誤就會少一個。所以要將所有的函 數都添加進去。

下面展示一下將所有的函數都添加之後的CPlugin類:

class CPlugin

{

public:

CPlugin(NPP pNPInstance);

~CPlugin();

// 關閉

void shut();

// 判斷是否進行了初始化

NPBool isInitialized();

// 初始化插件窗口

NPBool init(NPWindow* pNPWindow);

// 獲取一個處理消息的對象

NPObject *GetScriptableObject();

// 處理時間,但這裏只是對蘋果的事件進行了處理

int16_t handleEvent(voidevent);

private:

NPWindow * m_Window;

// 這個參數應該是沒有使用

NPStream * m_pNPStream;

// 保存插件是否進行了初始化工作

NPBool m_bInitialized;

// 保存提供方法對象

NPObject *m_pScriptableObject;

};

現在這個工程是可以編譯通過的。證明整個的工程的基本的框架是可以用的。下面就是 實現你的功能了。

首先說一下m_pScriptableObject 成員變量保存的是什麼。其實就是一個後面 會講到的一個類的對象。這個對象主要的作用就是處理插件提供給網頁端的函數處理 類。下面說一下這個類層次結構:

首先封裝一個類,這個類是繼承自NPObject類的,這個類是一個抽象類,所以我們封 裝一箇中間類,下面展示一下這個中間類:

class ScriptablePluginObjectBase : public NPObject

{

public:

ScriptablePluginObjectBase(NPP npp);

virtual ~ScriptablePluginObjectBase();

virtual void Invalidate();

virtual bool HasMethod(NPIdentifier name);

virtual bool Invoke(NPIdentifier name, const NPVariant *args,uint32_t argCount, NPVariant *result);

virtual bool InvokeDefault(const NPVariant *args, uint32_t argCount,NPVariant *result);

virtual bool HasProperty(NPIdentifier name);

virtual bool GetProperty(NPIdentifier name, NPVariant *result);

virtual bool SetProperty(NPIdentifier name, const NPVariant *value);

virtual bool RemoveProperty(NPIdentifier name);

virtual bool Enumerate(NPIdentifier **identifier, uint32_t *count);

virtual bool Construct(const NPVariant *args, uint32_t argCount, NPVariant *result);

public:

static void _Deallocate(NPObject *npobj);

static void _Invalidate(NPObject *npobj);

static bool _HasMethod(NPObject *npobj, NPIdentifier name);

static bool _Invoke(NPObject *npobj, NPIdentifier name,const NPVariant *args, uint32_t argCount,NPVariant *result);

static bool _InvokeDefault(NPObject *npobj, const NPVariant *args,uint32_t argCount, NPVariant *result);

static bool _HasProperty(NPObject * npobj, NPIdentifier name);

static bool _GetProperty(NPObject *npobj, NPIdentifier name,NPVariant *result);

static bool _SetProperty(NPObject *npobj, NPIdentifier name,const NPVariant *value);

static bool _RemoveProperty(NPObject *npobj, NPIdentifier name);

static bool _Enumerate(NPObject *npobj, NPIdentifier **identifier,uint32_t *count);

static bool _Construct(NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result);

protected:

NPP mNpp;

};

在上面的這個類中所有的函數幾乎都沒有實現,只是重寫了一下, 保存這個中間類不是一個抽象類。以後所有的操作類都繼承自這 箇中間類,就不必將所有的函數都重寫了。是程序的編寫更加的 方便。

下面看一下中間類都幹了些什麼吧,看看實現:

void ScriptablePluginObjectBase::Invalidate()

{

}

 

bool ScriptablePluginObjectBase::HasMethod(NPIdentifier name)

{

  return false;

}

 

bool ScriptablePluginObjectBase::Invoke(NPIdentifier nameconst NPVariant *argsuint32_t argCountNPVariant *result)

{

  return false;

}

 

bool ScriptablePluginObjectBase::InvokeDefault(const NPVariant *argsuint32_t argCountNPVariant *result)

{

  return false;

}

 

bool ScriptablePluginObjectBase::HasProperty(NPIdentifier name)

{

  return false;

}

 

bool ScriptablePluginObjectBase::GetProperty(NPIdentifier nameNPVariant *result)

{

  return false;

}

 

bool ScriptablePluginObjectBase::SetProperty(NPIdentifier nameconst NPVariant *value)

{

  return true;

}

 

bool ScriptablePluginObjectBase::RemoveProperty(NPIdentifier name)

{

  return false;

}

 

bool ScriptablePluginObjectBase::Enumerate(NPIdentifier **identifier,uint32_t *count)

{

  return false;

}

 

bool ScriptablePluginObjectBase::Construct(const NPVariant *argsuint32_t argCount,NPVariant *result)

{

  return false;

}

 

// static

void ScriptablePluginObjectBase::_Deallocate(NPObject *npobj)

{

  //調用虛析構函數

  delete (ScriptablePluginObjectBase *)npobj;

}

 

// static 刷新

void ScriptablePluginObjectBase::_Invalidate(NPObject *npobj)

{

  ((ScriptablePluginObjectBase *)npobj)->Invalidate();

}

 

// static 判斷NPIdentifier對應的函數是不是存在

bool ScriptablePluginObjectBase::_HasMethod(NPObject *npobjNPIdentifier name)

{

  return ((ScriptablePluginObjectBase *)npobj)->HasMethod(name);

}

 

// static

bool ScriptablePluginObjectBase::_Invoke(NPObject *npobjNPIdentifier name,const NPVariant *argsuint32_t argCount,NPVariant *result)

{

  return ((ScriptablePluginObjectBase *)npobj)->Invoke(nameargsargCount,result);

}

 

// static

bool ScriptablePluginObjectBase::_InvokeDefault(NPObject *npobj,const NPVariant *args,uint32_t argCount,NPVariant *result)

{

  return ((ScriptablePluginObjectBase *)npobj)->InvokeDefault(argsargCount,result);

}

 

// static

bool ScriptablePluginObjectBase::_HasProperty(NPObject * npobjNPIdentifier name)

{

  return ((ScriptablePluginObjectBase *)npobj)->HasProperty(name);

}

 

// static

bool ScriptablePluginObjectBase::_GetProperty(NPObject *npobjNPIdentifier name,NPVariant *result)

{

  return ((ScriptablePluginObjectBase *)npobj)->GetProperty(nameresult);

}

 

// static

bool ScriptablePluginObjectBase::_SetProperty(NPObject *npobjNPIdentifier name,const NPVariant *value)

{

  return ((ScriptablePluginObjectBase *)npobj)->SetProperty(namevalue);

}

 

// static

bool ScriptablePluginObjectBase::_RemoveProperty(NPObject *npobjNPIdentifier name)

{

  return ((ScriptablePluginObjectBase *)npobj)->RemoveProperty(name);

}

 

// static

bool ScriptablePluginObjectBase::_Enumerate(NPObject *npobj,NPIdentifier **identifier,uint32_t *count)

{

  return ((ScriptablePluginObjectBase *)npobj)->Enumerate(identifiercount);

}

 

// static

bool ScriptablePluginObjectBase::_Construct(NPObject *npobjconst NPVariant *args,uint32_t argCountNPVariant *result)

{

  return ((ScriptablePluginObjectBase *)npobj)->Construct(argsargCount,result);

}

看看實現吧,確實什麼都沒做。

下面就要看一下函數和屬性處理的具體的類了,這個類繼承自中間類,在其中實現你想要的函數即可,簡單實現如下所示:

class ScriptablePluginObject : public ScriptablePluginObjectBase

{

public:

ScriptablePluginObject(NPP npp);

~ScriptablePluginObject();

virtual bool HasMethod(NPIdentifier name);

virtual bool HasProperty(NPIdentifier name);

virtual bool GetProperty(NPIdentifier name, NPVariant *result);

virtual bool SetProperty(NPIdentifier name, const NPVariant *value);

virtual bool Invoke(NPIdentifier name, const NPVariant *args, uint32_t argCount, NPVariant *result);

virtual bool InvokeDefault(const NPVariant *args, uint32_t argCount, NPVariant *result);

public:

char m_szTextGui[200];

HWND m_hWnd;

private:

char *m_pszName;

};

具體裏面怎麼實現的就看demo中的代碼吧。這裏不再寫了,寫多了你也不想看。不如在vs上面看着舒服。

C、下面看一下NP插件的特殊的設置,如果不這樣設置,插件將不能被調用。

添加def文件,文件名npMySecond.def

LIBRARY   NPMYSECONDNP

EXPORTS

NP_GetEntryPoints   @1

NP_Initialize       @2

NP_Shutdown         @3

NP_GetMIMEDescription @4

前三個函數是必須導出的,第四個根據需要導出。

添加Version資源文件,npMySecond.rc

查看代碼,然後修改裏面的一些內容。

將block改爲 BLOCK "040904e4"

添加VALUE

VALUE "MIMEType""application/npMySecond"

 

經過上面的努力之後聲稱的插件就能用了。

下面介紹一下測試方法:

編輯註冊表
HKEY_CURRENT_USER\Software\MozillaPlugins下
新建子項@mozilla.com.cn/Second
並新建字符串值“Path”設值爲dll的全路徑

打開火狐瀏覽器 在地址欄輸入“about:plugins” 如果在plugin列表中有本例的npMySecondNp.dll及說明我們的plugin示例已經成功完成,
PS:
1.如果沒有,請再次查看BLOCK 的值是否是040904e4(僅僅是我遇到的)
2. 輸入about:config設置plugin.expose_full_path 設爲 true,可顯示dll全路徑

11.測試頁面

<HTML>
    <HEAD>
    </HEAD>
    <BODY>
        <embed type="application/npMySecond">
    </BODY>
</HTML>

源碼下載地址(不需要積分):http://download.csdn.net/detail/zdongfuyu/7729927
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章