Turn: Write the plug-in framework by yourself (2)

Source: Internet
Author: User

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

Plug-in programming interface

The so-called plug-in is actually an interface-based design. The most basic point of a plug-in-based system is to have a central system to load unknown plug-ins and be able to interact with these plug-ins using predefined interfaces and protocols.

The most basic way is to define an interface and provide a series of functions to be exposed by plug-ins (dynamic or static. This implementation is technically feasible, but it is not so simple. The reason is that a plug-in must support two types of interfaces, but only the function set of one interface can be exposed. This means that the two types of interfaces must be combined.

The first interface (Protocol) is a general plug-in interface. This interface allows the central system initialization plug-in to register the functions provided by the plug-in for object creation and destruction to the central system. This general plug-in interface is not related to specific fields, so it can be used as a reusable library. The second interface is the functional interface provided by the plug-in object. This interface is related to a specific domain and must be carefully designed and implemented by the plug-in. The central system should use this interface to interact with the plug-in object.

 

Next we will provide a general plug-in interface header file. Here, we will not go into details, just to have a relatively intuitive understanding.

 

 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_ProgrammingLanguage11 {12     PF_ProgrammingLanguage_C,13     PF_ProgrammingLanguage_CPP,14 }   PF_ProgrammingLanguage;15  16 struct PF_PlatformServices_;17  18 typedef struct PF_ObjectParams19 {20     const apr_byte_t * objectType;21     const struct PF_PlatformServices_ * platformServices;22 } PF_ObjectParams;23  24 typedef struct PF_PluginAPI_Version25 {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_RegisterParams35 {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_PlatformServices49 {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_API60   #ifdef WIN3261     #define PLUGIN_API __declspec(dllimport)62   #else63     #define PLUGIN_API64   #endif65 #endif66  67 extern68 #ifdef  __cplusplus69 "C"70 #endif71 PLUGIN_API PF_ExitFunc PF_initPlugin(const PF_PlatformServices * params);72  73 #ifdef  __cplusplus74 }75 #endif76  77 #endif /* PF_PLUGIN_H */

The first thing you need to realize is that this is a C header file. This allows our plug-in framework to be compiled and used by pure C systems, and to write pure C plug-ins. However, this does not limit the use of C. In fact, it has been designed to be more commonly used in C ++.

PF_ProgrammingLanguageEnumeration allows the plug-in to tell the plug-in manager whether it is implemented by C or C ++.

PF_ObjectParamsIs an abstract structure that is passed in when a plug-in object is created.

PF_PluginAPI_VersionUsed to specify the version information. This helps the plug-in Manager to load only compatible versions of plug-ins.

Function pointerPF_CreateFuncAndPF_DestroyFuncThe plug-in must be used to create and destroy plug-in objects in the plug-in manager.

PF_RegisterParamsThe structure contains all the information that the plug-in must provide to the plug-in manager, so that the plug-in manager can initialize the plug-in (version, create, destroy function, and development language ).

PF_RegisterFuncFunction pointers (implemented by the plug-in Manager) allow each plug-inPF_RegisterParamsStructure to register with the plug-in manager. Note: This implementation allows the plug-in to register objects of different versions and to register multiple object types.

PF_InvokeServiceA function pointer is a common function that allows a plug-in to call various services provided by the main system, such as logs, event processing, or error reports. This function requires a service name and an opaque pointer pointing to the parameter structure. Plug-ins should know available services and how to call them (or implement a service discovery mechanism ).

PF_PlatformServicesStructure is used to indicate all services provided by the platform (versions, registered objects, and called functions ). This structure is passed to each plug-in during plug-in initialization.

PF_ExitFuncIs the pointer to the plug-in exit function, implemented by the plug-in.

PF_InitFuncIs the function pointer of plug-in initialization.

PF_initPluginIs the actual Declaration of the function to be initialized by a dynamic plug-in (that is, the plug-in deployed through a dynamically linked library or shared library. It is exposed by the dynamic plug-in, so the plug-in manager can call it when loading the plug-in. It has a pointPF_PlatformServicesStructure pointer, so these services can be called during plug-in initialization (this is the ideal time to register the object), and the function returns the pointer to exit the function.

For static plug-ins (implemented by the static Link Library and directly linked to the main application ),initFunction,NoName itPF_initPlugin. The reason is that if there are multiple static plug-ins, they cannot have functions with the same name.

The initialization process of static plug-ins is different. They must be explicitly initialized by the main program, that is, throughPF_InitFuncCall its initialization function. This is actually a poor design, because if you want to add or delete static plug-ins, the main application code must be modified, and those with different namesinitAll functions must be located.

There is a technology called "Automatic Registration" trying to solve this problem. Automatic Registration is implemented by the global object of a static database. This object willmain()The construction is completed before the function is executed. This global object can request the plug-in Manager to initialize the static plug-in (by passing the plug-ininit()Function pointer ). Unfortunately, in some versions of Visual C ++, this technology is not supported.

Compile plug-ins

How to compile the plug-in? Our plug-in framework provides the most common functions. It is difficult to add plug-ins that can interact with the main application under current conditions. Therefore, you must build your own application objects based on the plug-in framework again. This means that your applications (loaded plug-ins), together with the plug-in itself, must comply with the same interaction model. This usually means that the application requires the plug-in to provide specific types of objects for exposing certain APIs. The plug-in Framework provides all the required public basic code for plug-in registration, enumeration, and loading.

The following example is defined by the C ++ interface.IActor. This interface has two operations:getInitialInfo()Andplay(). Note that this interface is not sufficient for all situations, becausegetInitialInfo()The function must pointActorInfoStructure pointer, andplay()You need another interface.ITurnPointer. This is often the case. You must design this way and specify a specific object model.

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

Each plug-in can be registeredIActorMultiple implementations of the interface. When the application decides to instantiate an object registered by the plug-in, it callsPF_CreateFuncFunction. The plug-in will respond, create an object and return it to the application. Function return value isvoid *Because the object creation operation is part of the general plug-in framework, you do not know any specificIActorInterface Information. The application is responsiblevoid *ConvertIActor *And then call its functions through interfaces like other objects. When the application is used upIActorThe registeredPF_DestroyFuncFunction, the plug-in will destroy this object. As to why virtual destructor are required, we will discuss it later.

Turn: Write the plug-in framework by yourself (2)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.