为应用程序添加插件功能

    现在很多程序都支持插件,有利于程序功能的扩展.也方便用户为程序定制一些个性化的功能.
    实现的方法有很多,主要目的是将插件与应用程序的接口实现好就可以了,至于插件格式,这里我选用的是DLL.
    首先,要定义一个保存插件信息的结构:

typedef struct _Plugin_T
{
 //
 // 插件的名称
 //
 char  szPluginName[256];

 //
 // DLL的实例句柄
 //
 HINSTANCE hPlugin;

 //
 // 插件中处理命令行的函数
 //
 void (*pfn_get_cmd_line)(char* cmdline);

} PLUGIN_T, *LPPLUGIN_T;

    现在还需要一个容器结构将插件的信息组织起来,方便调用,如下:

struct _Plugin_Vector
{
 PLUGIN_T  Plugins[50];

 //
 // 插件计数
 //
 unsigned int nCount;
} g_pv;

    这里为了演示,预设50个插件(如果你很喜欢STL的话,可以使用vector来作为容器,这样会看起来更Cool).
    有了上面两个结构,load_plugin()就可以根据用户的输入来载入相应的插件.代码如下:

int load_plugin(char* szFileName)
{
 //
 // 取得dll的实例句柄
 //
 g_pv.Plugins[g_pv.nCount].hPlugin = LoadLibrary(szFileName);
 if(g_pv.Plugins[g_pv.nCount].hPlugin == NULL)
 {
  fprintf(stderr, "LoadLibrary() failed. --err: %d/n", GetLastError());
  return -1;
 }

 //
 // 取得插件名.由于szFileName包含文件的扩展名(.dll),
 // 所以要将扩展名去掉
 //
 char  szPluginName[256];
 char* p = 0;
 strcpy(szPluginName, szFileName);
 p = strchr(szPluginName, '.');
 *p = '/0';

 strcpy(g_pv.Plugins[g_pv.nCount].szPluginName, szPluginName);

 //
 // 取得插件中处理命令行的函数指针(插件的导出函数)
 //
 g_pv.Plugins[g_pv.nCount].pfn_get_cmd_line = (void (*)(char*))GetProcAddress(g_pv.Plugins[g_pv.nCount].hPlugin, "get_cmd_line");

 printf("Plugin %s Load Ok!/n", g_pv.Plugins[g_pv.nCount].szPluginName);
 g_pv.nCount++;

 return 0;
}

    这样就可以通过.load <dll name>来加载所需要的插件,如:.load hack.dll(需要带扩展名).主程序中由get_cmd_line()来负责对输入的命令进行处理,代码如下:

void get_cmd_line()
{
 char cmdline[256];

 printf("cdsh# ");
 gets(cmdline);

 while(stricmp(cmdline, ".quit"))
 {
  if( !strnicmp(cmdline, ".load", 5) )
  {
   char* p = strchr(cmdline, ' ');
   if(p != NULL)
    load_plugin(p+1);
   else
    show_loaded_plugin();
  }
  else
   get_plugin_cmd_line(cmdline);

  printf("/ncdsh# ");
  gets(cmdline);
  
 }
}

    get_cmd_line()首先要检查输入是否是应用程序所能处理的命令,如果不是,将调用get_plugin_cmd_line()将输入传递给相应的插件进行处理.调用插件的命令行为<插件名> <命令行>,例如:hack .help 表示调用hack插件的.help命令.
    get_plugin_cmd_line()的代码如下:

void get_plugin_cmd_line(char* cmdline)
{
 char* pch_space;
 char plugin_name[256];
 char plugin_cmd_line[256];

 pch_space = strchr(cmdline, ' ');

 //
 // 检查传递给插件的命令格式是否正确
 //
 if(pch_space == NULL) return;

 int i = 0;
 char* p = NULL;
 
 //
 // 取得调用插件的名称
 //
 for(i = 0, p = cmdline; p < pch_space; i++, p++)
  plugin_name[i] = *p;
 plugin_name[i] = '/0';
 
 //
 // 取得命令行
 //
 for(i = 0, p = pch_space + 1; *p != '/0'; i++, p++)
  plugin_cmd_line[i] = *p;
 plugin_cmd_line[i] = '/0';


 //
 // 找出要调用的插件,执行命令
 //
 for(i = 0; i < g_pv.nCount; i++)
 {
  if( !stricmp(g_pv.Plugins[i].szPluginName, plugin_name) ) break;
 }

 g_pv.Plugins[i].pfn_get_cmd_line(plugin_cmd_line);
}

    现在载入插件与执行插件的操作都已经成功了,还剩下一步,由于调用LoadLibrary()来载入的插件,在程序结束时需要调用FreeLibrary()来释放资源,代码如下:

void free_plugin()
{
 for(int i = 0; i < g_pv.nCount; i++)
 {
  FreeLibrary(g_pv.Plugins[i].hPlugin);
  g_pv.Plugins[i].pfn_get_cmd_line = NULL;
  memset(g_pv.Plugins[i].szPluginName, 0, 256);
 }
}

    最后来看一下插件的编写,只需要编写一个dll并且导出其中的get_cmd_line()便可以了,至于其他的功能,可以在处理命令行的过程中实现.作为实例,我做了一个hack.dll,代码如下:

#include <stdio.h>
#include <windows.h>

#define __dll_export extern "C" __declspec(dllexport)

__dll_export void get_cmd_line(char* cmdline)
{
 if(!stricmp(cmdline, ".help"))
  printf("[In Hack.dll]HackIt! uha.../n");
}

    以上便是整个的实现思路,还剩余一些问题,比如在这个程序中,我没有处理多次加载同一个插件的情况.如果大家感兴趣可以自己解决一下.
    其实对于插件的支持,使用面向对象的方法来解决问题的话,会比现在简单的多,构造一个插件类,重载其中的功能函数,之后通过对象的指针来进行调用...

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在gstreamer应用程序开发,要调用插件接口,可以按照以下步骤进行: 1. 创建GStreamer的pipeline:创建一个GstPipeline对象,作为音视频流的处理管道。 2. 加载插件:使用gst_element_factory_make()函数来加载所需的插件。该函数接受插件的类型和插件名称作为参数,并返回一个对应的GstElement对象。 3. 连接元素:使用gst_element_link()函数将不同的GstElement对象连接起来,形成数据流的处理链。通过将源元素和目标元素传递给该函数,可以将它们连接起来。 4. 配置插件属性:对需要的插件进行属性设置。可以使用gst_element_set_property()函数为插件设置属性值,也可以使用gst_element_get_property()函数获取属性的当前值。 5. 监听事件:为需要监听特定事件的插件添加相应的事件处理器。可以通过使用gst_element_add_event_probe()函数来添加事件探针,该函数将在触发特定事件时调用相应的回调函数。 6. 启动流媒体流:使用gst_element_set_state()函数将pipeline设置为播放状态,开始处理音视频数据流。 7. 处理数据:处理从插件接收到的数据。可以通过连接插件的src pad和sink pad来获取输入和输出数据,并在处理数据时使用对应的回调函数。 8. 监听信号:为需要监听信号的插件添加相应的信号处理函数。使用g_signal_connect()函数将信号与回调函数连接起来,在触发信号时执行相应的操作。 9. 控制流媒体流:使用gst_element_set_state()函数将pipeline设置为停止状态,结束数据的处理。 总之,调用插件接口的关键是正确配置和连接GstElement对象,以及使用适当的函数设置和获取属性值、添加事件探针和信号处理函数。以上步骤可以帮助开发者在gstreamer应用程序调用插件接口。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值