【转】我的Firefox插件开发之旅(7)——为插件添加和脚本交互的能力(转)

先说一句题外话,上一节一开始我提到了由于.rc导致我自己写的插件不能被FF识别的问题,今天终于找到答案了。在这篇文章中:https://developer.mozilla.org/en/Gecko_Plugin_API_Reference/Plug-in_Development_Overview, 有这么一段话:In your development environment, make sure your language is set to "US English" and the character set to "Windows Multilingual." The resource code for this language and character set combination is 040904E4. 看来这FF还只能使用英文。

OK,步入正题。这一小节我来简单说一下如何为插件添加和脚本语言(如Javascript)交互的能力。我会为插件添加几个函数,供Javascript调用。

前面我们提到过浏览器调用插件的方法的顺序,基本上为:NP_GetEntryPoints、NP_Initialize、NPP_New、 NPP_SetWindow、NPP_GetValue。在NPP_New中,我们需要创建插件对象的实例,NPP_SetWindow中,浏览器会传入 插件窗口的信息,最后一个NPP_GetValue,是浏览器来获取一些插件信息的。NPP_GetValue函数的结构是这样的:

NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value);

  • instance包含着插件对象实例;
  • variable表示浏览器要获取的信息的类型;
  • value表示返回给浏览器的值

浏览器会传入NPPVpluginScriptableNPObject(作为variable参数)来查询插件是否支持 Scriptable功能(即和脚本语言交互的功能),在这里,我们可以利用NPN_CreateObject方法来创建一个NPObject对象,并且 作为value返回给浏览器。这样,浏览器就通过这个NPObject对象和我们的插件建立了连接。当页面上Javascript调用了我们插件对象的某 个方法时,浏览器会调用该NPObject对象的HasMethod方法来查询是否支持这个方法,如果支持,则会调用NPObject对象的Invoke 方法,传入方法名、参数等信息。这样,我们就可以让网页上的脚本语言来执行我们编写的函数了。在Windows上,我们编写的函数就如同编写普通的应用程 序一样,可以使用很多Windows API来完成许多复杂的工作。

上面有个问题:如何创建我们自己的NPObject对象?NPN_CreateObject方法如何使用?好在Mozilla给我们提供了npruntime这个例子程序,可以让我们得以参考。

先来看看NPN_CreateObject方法的定义:

NPObject *NPN_CreateObject(NPP npp, NPClass *aClass);

关键在第二个参数上,我们需要提供一个NPClass指针。npruntime例子程序中是这么做的:

定义了一个宏DECLARE_NPOBJECT_CLASS_WITH_BASE,其作用就是定义了一个静态的NPClass对象,并且 NPClass要求的所有基础方法,都由一个ScriptablePluginObjectBase类来提供。我们根据需要,来创建不同的继承于 ScriptablePluginObjectBase的类(比如支持方法的类和支持属性的类),传给 DECLARE_NPOBJECT_CLASS_WITH_BASE宏,这样,当浏览器管我们“要”的时候,我们就可以按照它的需要“给”它对应的对象。

npruntime例子中,ScriptablePluginObject是用来处理方法的,而ConstructablePluginObject是用来处理属性的。

如何定义一个方法(或属性)?

1、添加一个方法(或属性)很简单,先定义一个静态NPIdentifier类型的变量,例如:

static NPIdentifier s_idSetArgs;

2、在插件对象构造函数中,使用NPN_GetStringIdentifier方法来设置该方法的名称,例如:

s_idSetArgs = NPN_GetStringIdentifier("SetArgs");

其中,SetArgs就是我们提供给脚本语言调用的方法名称。

3、在ScriptablePluginObject的HasMethod方法中,判断传入的方法名:

bool ScriptablePluginObject::HasMethod(NPIdentifier name)
{
if(name == s_idSetArgs)
{
printf("method name = SetArgs\n");
return true;
}

    return false;
}

4、在ScriptablePluginObject的Invoke方法中,判断如果传入的方法名称等于我们定义的方法名,则做你想要做得事情:

//////////////////////////////////////////////////////////////////////////
///
/// @brief    如果某个方法支持(使用HasMethod检测),当页面上Javascript代码调用该方法时,会执行本函数
///
/// @param [in] name    方法名
/// @param [in] args    参数值(数组)
/// @param [in] argCount    参数个数
/// @param [in] result    执行后返回给调用者的结果
///
/// @return PR_TRUE表示执行成功,PR_FALSE表示失败
///
//////////////////////////////////////////////////////////////////////////

bool ScriptablePluginObject::Invoke(NPIdentifier name, const NPVariant *args, uint32_t argCount, NPVariant *result)

{
if(name == s_idSetArgs)

    {

        这里做你想要做得事情

        return PR_TRUE;

    }

    return PR_FALSE;

}

关于方法参数的接收,这里举个例子。比如网页上这么调用:

embedobj.SetArgs("name", "value");

在我们的方法中,就可以这么接收:

if(args != NULL && argCount >= 2)
{
NPVariant npvName = args[0]; //第一个参数
NPVariant npvValue = args[1]; //第二个参数
if(NPVARIANT_IS_STRING(npvName) && NPVARIANT_IS_STRING(npvValue)) //如果两者都是字符串类型(当然你还可以判断是否是其他类型)
{
NPString npsName = NPVARIANT_TO_STRING(npvName); //转成NPString
NPString npsValue = NPVARIANT_TO_STRING(npvValue);

        if(npsName.utf8characters && strlen(npsName.utf8characters) > 0) //限定条件,可以根据需要进行修改。这里限定第一个参数内容不能为空
{
int nLenName = strlen(npsName.utf8characters) + 1;
int nLenValue = strlen(npsValue.utf8characters) + 1;

            PARAMPAIR paramPair;
paramPair.pName = new char[nLenName];
memset(paramPair.pName, 0, nLenName);
paramPair.pValue = new char[nLenValue];
memset(paramPair.pValue, 0, nLenValue);

            strcpy(paramPair.pName, npsName.utf8characters); //将参数内存存储到我们熟悉的C
strcpy(paramPair.pValue, npsValue.utf8characters);

            m_vecParamPair.push_back(paramPair);
}
}
}

上面的代码中,PARAMPAIR就是一个简单的结构体:

typedef struct tagPARAMPAIR
{
LPTSTR pName;
LPTSTR pValue;
}PARAMPAIR, *PPARAMPAIR;

m_vecParamPair是一个vector:vector<PARAMPAIR> m_vecParamPair;

顺便说一句,上面只是代码片段,关于内存释放、vector清空等操作,由于不是这里要说的关键部分,所以没有列出。

OK,现在我们的插件已经可以顺利和网页进行交互工作了。

提供了基于BP(Back Propagation)神经网络结合PID(比例-积分-微分)控制策略的Simulink仿真模型。该模型旨在实现对杨艺所著论文《基于S函数的BP神经网络PID控制器及Simulink仿真》中的理论进行实践验证。在Matlab 2016b环境下开发,经过测试,确保能够正常运行,适合学习研究神经网络在控制系统中的应用。 特点 集成BP神经网络:模型中集成了BP神经网络用于提升PID控制器的性能,使之能更好地适应复杂控制环境。 PID控制优化:利用神经网络的自学习能力,对传统的PID控制算法进行了智能调整,提高控制精度稳定性。 S函数应用:展示了如何在Simulink中通过S函数嵌入MATLAB代码,实现BP神经网络的定制化逻辑。 兼容性说明:虽然开发于Matlab 2016b,但理论上兼容后续版本,可能会需要调整少量配置以适配不同版本的Matlab。 使用指南 环境要求:确保你的电脑上安装有Matlab 2016b或更高版本。 模型加载: 下载本仓库到本地。 在Matlab中打开.slx文件。 运行仿真: 调整模型参数前,请先熟悉各模块功能输入输出设置。 运行整个模型,观察控制效果。 参数调整: 用户可以自由调节神经网络的层数、节点数以及PID控制器的参数,探索不同的控制性能。 学习修改: 通过阅读模型中的注释查阅相关文献,加深对BP神经网络与PID控制结合的理解。 如需修改S函数内的MATLAB代码,建议有一定的MATLAB编程基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值