转:自己动手写插件框架(2)

转自:http://www.devbean.net/2012/03/building-your-own-plugin-framework-2/

插件编程接口

所谓插件,其实就是基于接口的设计。基于插件的系统最基本的一点就是,要有一个中心系统,用于加载未知的插件,并且能够使用预先定义好的接口和协议与这些插件进行交互。

最基本的方式是定义一个接口,提供一系列插件(动态的或者是静态)需要暴露出的函数。这种实现从技术上说是可行的,但实际并不那么简单地操作。原因在于,一个插件需要支持两类接口,但是却只能暴露出一个接口的函数集。这意味着,两类接口必须混合在一起。

第一个接口(协议)是通用插件接口。该接口允许中心系统初始化插件,能够将插件提供的用于创建、销毁对象的函数注册给中心系统。这个通用插件接口不是特定领域相关的,因此能够作为一个可复用库。第二个接口则是插件对象提供的功能接口。这个接口是与特定领域相关的,必须被仔细地设计,并且由插件实际实现。中心系统应当利用这个接口与插件对象进行交互。

 

下面我们给出一个通用插件接口的头文件。这里,我们不会深究细节,仅仅为了有个相对直观地认识。

 

 1 #ifndef PF_PLUGIN_H
 2 #define PF_PLUGIN_H
 3  
 4 #include <apr-1/apr_general.h>
 5  
 6 #ifdef __cplusplus
 7 extern "C" {
 8 #endif
 9  
10 typedef enum PF_ProgrammingLanguage
11 {
12     PF_ProgrammingLanguage_C,
13     PF_ProgrammingLanguage_CPP,
14 }   PF_ProgrammingLanguage;
15  
16 struct PF_PlatformServices_;
17  
18 typedef struct PF_ObjectParams
19 {
20     const apr_byte_t * objectType;
21     const struct PF_PlatformServices_ * platformServices;
22 } PF_ObjectParams;
23  
24 typedef struct PF_PluginAPI_Version
25 {
26     apr_int32_t major;
27     apr_int32_t minor;
28 } PF_PluginAPI_Version;
29  
30 typedef void * (*PF_CreateFunc)(PF_ObjectParams *);
31  
32 typedef apr_int32_t (*PF_DestroyFunc)(void *);
33  
34 typedef struct PF_RegisterParams
35 {
36     PF_PluginAPI_Version version;
37     PF_CreateFunc createFunc;
38     PF_DestroyFunc destroyFunc;
39     PF_ProgrammingLanguage programmingLanguage;
40 } PF_RegisterParams;
41  
42 typedef apr_int32_t (*PF_RegisterFunc)(const apr_byte_t * nodeType,
43                                        const PF_RegisterParams * params);
44  
45 typedef apr_int32_t (*PF_InvokeServiceFunc)(const apr_byte_t * serviceName,
46                                             void * serviceParams);
47  
48 typedef struct PF_PlatformServices
49 {
50     PF_PluginAPI_Version version;
51     PF_RegisterFunc registerObject;
52     PF_InvokeServiceFunc invokeService;
53 } PF_PlatformServices;
54  
55 typedef apr_int32_t (*PF_ExitFunc)();
56  
57 typedef PF_ExitFunc (*PF_InitFunc)(const PF_PlatformServices *);
58  
59 #ifndef PLUGIN_API
60   #ifdef WIN32
61     #define PLUGIN_API __declspec(dllimport)
62   #else
63     #define PLUGIN_API
64   #endif
65 #endif
66  
67 extern
68 #ifdef  __cplusplus
69 "C"
70 #endif
71 PLUGIN_API PF_ExitFunc PF_initPlugin(const PF_PlatformServices * params);
72  
73 #ifdef  __cplusplus
74 }
75 #endif
76  
77 #endif /* PF_PLUGIN_H */

你需要认识到的第一件事是,这是一个 C 头文件。这就允许我们的插件框架能够被纯 C 系统编译和使用,并且能够编写纯 C 插件。但是,这么做并不会限定必须使用 C,实际上,它已经被设计为更常用 C++ 来实现。

PF_ProgrammingLanguage枚举允许插件告诉插件管理器,它本身是由 C 还是 C++ 实现的。

PF_ObjectParams是一个抽象结构,在创建插件对象时被传入。

PF_PluginAPI_Version用于指明版本信息。这有助于插件管理器只加载兼容版本的插件。

函数指针PF_CreateFuncPF_DestroyFunc必须由插件实现,用于插件管理器创建和销毁插件对象。

PF_RegisterParams结构包含了插件必须提供给插件管理器的所有信息,以便插件管理器初始化插件(版本,创建、销毁函数以及开发语言)。

PF_RegisterFunc函数指针(由插件管理器实现)允许每个插件将其支持的对象类型以PF_RegisterParams结构的形式注册给插件管理器。注意,这种实现允许插件注册不同版本的对象,以及注册多个对象类型。

PF_InvokeService函数指针是一个通用函数,允许插件调用主系统提供的各种服务,例如日志、事件处理或者错误报告等。该函数要求有一个服务名称以及一个指向参数结构的不透明的指针。插件应当知道可用的服务以及如何调用它们(或者实现一种服务发现机制)。

PF_PlatformServices结构用于表示平台提供的所有服务(版本、已注册对象和调用函数)。该结构会在插件初始化的时候传给每一个插件。

PF_ExitFunc是插件退出函数的指针,由插件实现。

PF_InitFunc是插件初始化的函数指针。

PF_initPlugin是动态插件(也就是通过动态链接库或者共享库部署的插件)初始化函数的实际声明。它由动态插件暴露出,所以插件管理器可以在加载插件时进行调用。它有一个指向PF_PlatformServices结构的指针,所以在插件初始化时,这些服务都是可以调用的(这正是注册对象的理想时机),函数返回退出函数的指针。

而对于静态插件(由静态链接库实现,并且直接与主应用程序链接的插件)应该实现init函数,但是不能命名为PF_initPlugin。原因是,如果有多个静态插件,它们不能有相同的名字的函数。

静态插件的初始化过程有所不同。它们必须由主程序显式地进行初始化,也就是通过PF_InitFunc调用其初始化函数。这实际是不好的设计,因为如果要新增或者删除静态插件,主应用的代码都必须修改,并且那些不同名字的init函数都必须能够找到。

有一个叫做“自动注册”的技术试图解决这个问题。自动注册由一个静态库的全局对象实现。该对象会在main()函数执行之前构造完成。这个全局对象能够请求插件管理器初始化静态插件(通过传递插件init()函数的指针来完成)。不幸的是,在某些版本的 Visual C++ 中,这种技术并不支持。

编写插件

如何编写插件?我们的插件框架提供了最通用的功能,在目前的条件下很难添加能够与主应用交互的插件。所以,你必须再次插件框架的基础之上构建自己的应用程序对象。这意味着,你的应用程序(加载插件的)连同插件本身,都必须遵守同一个交互模型。通常这代表,应用程序需要插件提供特定类型的对象,用于暴露某些特定的 API。插件框架提供所有必须的公共基础代码,用于插件的注册、枚举以及加载。

下面的例子是 C++ 接口定义的IActor。这个接口有两个操作:getInitialInfo()play()。注意,这个接口并不足以应付所有情况,因为getInitialInfo()函数需要一个指向ActorInfo结构的指针,而play()则需要另外一个接口ITurn的指针。这是经常遇见的情况,你必须这么设计,并且指定一个特定的对象模型。

1 struct IActor
2 {
3     virtual ~IActor() {}
4     virtual void getInitialInfo(ActorInfo * info) = 0;
5     virtual void play( ITurn * turnInfo) = 0;
6 };

每个插件都可以注册IActor接口的多个实现。当应用程序决定实例化一个由插件注册的对象时,它就调用由插件实现的PF_CreateFunc函数。插件就会做出响应,创建对象并返回给应用程序。函数返回值是void *,因为对象的创建操作是通用插件框架的一部分,因此并不知道任何关于特定的IActor接口的信息。应用程序负责将void *转换成IActor *,然后像其他对象一样通过接口调用其函数。当应用程序使用完IActor对象时,会调用注册的PF_DestroyFunc函数,插件就销毁该对象。至于为什么需要有虚析构函数,我们会在以后的讨论中介绍。

转载于:https://www.cnblogs.com/kira2will/p/3940571.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: C 插件框架 demo 是一个用于展示 C 语言的插件框架示例。插件框架是一种允许用户在应用程序中动态加载和卸载插件的架构。这个 demo 展示了如何使用 C 语言来实现一个基本的插件系统。 首先,我们需要定义插件的接口,以便应用程序能够与插件进行交互。接口定义了插件所必须实现的函数和数据结构。接口中的函数可以是回调函数,用于应用程序调用插件中的功能。 然后,我们可以定义插件的结构体,其中包含插件的元数据和实现接口函数的函数指针。这些函数指针将在插件加载时进行赋值,以便应用程序能够调用插件的功能。 接下来,我们需要实现一个插件管理器,用于动态加载和卸载插件插件管理器可以扫描指定目录下的插件文件,并将其加载到应用程序中。加载插件时,插件管理器会使用 dlopen 函数将插件文件加载到内存中,并获取插件的函数指针。卸载插件时,插件管理器会使用 dlclose 函数将插件从内存中移除。 最后,我们可以编一个简单的应用程序,使用插件框架来扩展其功能。这个应用程序可以使用插件管理器加载各种插件,并调用插件中的函数来执行相应的操作。 通过这个 C 插件框架 demo,我们可以了解到插件框架的基本原理和实现方式。使用插件框架可以使应用程序更加灵活和可扩展,用户可以根据需要自定义和添加插件,以满足不同的功能需求。 ### 回答2: 插件框架 demo是指一个展示插件框架功能和用法的示例程序。插件框架是一种允许开发者轻松扩展和定制应用程序功能的架构。通过使用这个框架,开发者可以开发自己的插件,并将其集成到应用程序中,增加新的功能或修改现有功能。插件框架提供了一种灵活的方式来定制应用程序,使其可以满足不同用户或场景的需求。 插件框架 demo通常包含以下内容: 1. 插件注册和加载:演示如何将插件注册到框架中,并实现插件的加载和初始化过程。通过这个示例,开发者可以学习到如何管理和控制插件的生命周期。 2. 插件接口和扩展点:插件框架通常定义了一些接口和扩展点,插件可以实现这些接口,并通过扩展点与应用程序进行交互。演示示例应该展示如何创建接口和扩展点,并在插件中实现它们。 3. 插件运行时环境:插件框架通常提供了一个运行时环境,用于加载和执行插件。演示示例应该展示如何配置和启动这个运行时环境,并演示插件的加载和执行过程。 4. 插件的使用和调试:演示示例应该展示如何在应用程序中使用已经加载的插件,并提供一些调试工具和方法,以便开发者能够更好地查看和调试插件的运行时数据。 通过这个插件框架 demo,开发者可以快速入门并理解插件框架的概念和用法,为开发自己的插件提供了一个良好的起点。希望通过这个示例能够帮助开发者更好地使用和扩展应用程序的功能。 ### 回答3: c插件框架demo是指以C语言为基础构建的插件框架展示。插件是一种独立的软件模块,可以在应用程序中动态加载和卸载,以增强其功能。插件框架则是为插件的管理和扩展提供支持的软件架构。 在c插件框架demo中,首先需要定义插件的基本结构和接口。每个插件都应该包括一个初始化函数和一个功能函数。初始化函数用于初始化插件的环境,功能函数则是插件的具体功能实现。通过定义统一的接口,可以方便地管理和调用各个插件。 接下来,在框架中实现插件的加载和卸载功能。插件可以存储在特定的目录中,框架通过读取插件目录获取所有的插件文件,并将它们加载到内存中。加载后,框架调用插件的初始化函数来进行初始化工作。当不需要插件时,可以通过调用插件的卸载函数将其从内存中卸载。 此外,框架还需要提供插件的管理功能。可以实现插件的启动、停止和重启等操作。同时,框架可以提供插件的配置接口,允许用户对插件进行配置和自定义。 最后,在c插件框架demo中,可以编一些示例插件来展示其应用和功能。示例插件可以实现一些常见的功能,如文件操作、网络通信等。通过演示这些插件,可以帮助用户更好地理解和使用插件框架。 总之,c插件框架demo通过展示插件的加载、卸载和管理等功能,为用户提供了一个灵活且易于扩展的软件架构。用户可以根据自己的需求,编或集成各种插件,从而为应用程序增加更多的功能和特性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值