火狐NP插件开发 C++

来源:互联网 发布:收银软件库存一体 编辑:程序博客网 时间:2024/06/06 13:18

 由于接触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
1 0
原创粉丝点击