📄 plugin.h
字号:
/* * Copyright (C) 2000 Alan Robertson <alanr@unix.sh> * This software licensed under the GNU LGPL. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */#ifndef PILS_PLUGIN_H# define PILS_PLUGIN_H# include <ltdl.h>/* Glib headers generate warnings - so we make them go away */#define time FOOtime#define index FOOindex#include <glib.h>#undef index#undef time/***************************************************************************** * PILS - Universal Plugin and Interface loading system ***************************************************************************** * * An Overview of PILS... * * PILS is fairly general and reasonably interesting plugin loading system. * We manage both plugins and their interfaces * * This plugin / interface management system is quite general, and should be * directly usable by basically any project on any platform on which it runs * - which should be many, since everything is build with automake * and libtool. * * Some terminology... * * There are two basic kinds of objects we deal with here: * * Plugins: dynamically loaded chunks of code which implement one or more * interfaces. The system treats all plugins as the same. * In UNIX, these are dynamically loaded ".so" files. * * Interface: A set of functions which implement a particular capability * (or interface) * Generally interfaces are registered as part of a plugin. * The system treats all interfaces of the same type the same. * It is common to have exactly one interface inside of each plugin. * In this case, the interface name should match the plugin name. * * Each interface implementation exports certain functions for its clients * to use. We refer to these those "Ops". Every interface of the same type * "imports" the same interfaces from its interface manager, * and exports the same "Ops". * * Each interface implementation is provided certain interfaces which it * imports when it from its interface manager when it is registered. * We refer to these as "Imports". Every interface of a given type * imports the same interfaces. * * The story with plugins is a little different... * * Every plugin exports a certain set of interfaces, regardless of what type * of interfaces is implemented by it. These are described in the * PILPluginOps structure. * * Every plugin imports a certain set of interfaces, regardless of what type * of interfaces it may implement. These are described by the * PILPluginImports structure. * * In the function parameters below, the following notation will * sometimes appear: * * (OP) == Output Parameter - a parameter which is modified by the * function being called * * ***************************************************************************** * * The basic structures we maintain about plugins are as follows: * * PILPlugin The data which represents a plugin. * PILPluginType The data common to all plugins of a given type * PILPluginUniv The set of all plugin types in the Universe * (well... at least *this* universe) * * The basic structures we maintain about interfaces are as follows: * PILInterface The data which represents a interface * PILInterfaceType The data which is common to all * interfaces of a given type * PILPluginUniv The set of all interface types in the Universe * (well... at least *this* universe) * * Regarding "Universe"s. It is our intent that a given program can deal * with plugins in more than one universe. This might occur if you have two * independent libraries each of which uses the plugin loading environment * to manage their own independent interface components. There should be * no restriction in creating a program which uses both of these libraries. * At least that's what we hope ;-) * * *************************************************************************** * SOME MORE DETAILS ABOUT PLUGINS... *************************************************************************** * * Going back to more detailed data structures about plugins... * * PILPluginImports The set of standard functions all plugins * import. * This includes: * register_plugin() * unregister_plugin() * register_interface() * unregister_interface() * load_plugin() * log() Preferred logging function * * PILPluginOps The set of standard operations all plugins * export. * This includes: * pluginversion() * pluginname() * getdebuglevel() * setdebuglevel() * close() Prepare for unloading... * * Although we treat plugins pretty much the same, they are still * categorized into "types" - one type per directory. These types * generally correspond to interface types. * * One can only cause a plugin to be loaded - not a interface. But it is * common to assume that loading a plugin named foo of type bar will * cause a interface named foo of type bar to be registered. If one * wants to implement automatic plugin loading in a given interface type, * this assumption is necessary. * * The general way this works is... * * - A request is made to load a particular plugin of a particular type. * * - The plugin is loaded from the appropriate directory for plugins * of that type. * * - The ml_plugin_init() function is called once when the plugin is * loaded. * * The ml_plugin_init() function is passed a vector of functions which * point to functions it can call to register itself, etc. * (it's of type PILPluginImports) * * The ml_plugin_init function then uses this set of imported functions * to register itself and its interfaces. * * The mechanism of registering a interface is largely the same for * every interface. However, the semantics of registering a interfaces * is determined by the interface manager for the particular type of * interface being discussed. * *************************************************************************** * SOME MORE DETAILS ABOUT PLUGINS... *************************************************************************** * * There is only one built in type of interface. That's the Interface * manager interface. * The interface manager for the interface of type "InterfaceMgr", * named "InterfaceMgr" inserts itself into the system in order * to bootstrap things... * * When an attempt is made to register a interface of an unknown type, * then the appropriate Interface manager is loaded automatically. * * The name of an interface manager determines the type of * interface it manages. * * It handles requests for interfaces whose type is the same * as its interface name. If the interface manager's interface name * is foo, then it is the interface manager for all interfaces whose * type is foo. * * Types associated with interfaces of type Interface * * PILInterfaceOps The set of interfaces that every interface * manager exports * PILInterfaceImports The set of interfaces which are supplied to * (imported by) every interface of type * Interface. (that is, every interface * manager). * ***************************************************************************** * * Each plugin has only one entry point which is exported directly, regardless * of what kind of interface(s) it may implement... * * This entrypoint is named ml_plugin_init() {more or less - see below} * * The ml_plugin_init() function is called once when the plugin is loaded. * * * All other function pointers are registered (exported) through parameters * passed to ml_plugin_init() * * It is the purpose of the Ml_plugin_init() to register the plugin, * and all the interfaces which this plugin implements. A pointer to * the registration function is in the parameters which are passed * to ml_plugin_init(). * ***************************************************************************** * * THINGS IN THIS DESIGN WHICH ARE PROBABLY BROKEN... * * It may also be the case that the plugin loading environment needs * to be able to have some kind of user_data passed to it which it can * also pass along to any interface ... * * Maybe this should be handled by a sort of global user_data registration * structure, so globals can be passed to interfaces when they're registered. * * A sort of "user_data" registry. One for each interface type and one * for each interface... Or maybe it could be even more flexible... * * This is all so that these nice pristene, beautiful concepts can come out * and work well in the real world where interfaces need to interact with * some kind of global system view, and with each other... * * Probably need some better way of managing interface versions, etc. * **************************************************************************** *//* * If you want to use this funky export stuff, then you need to #define * PIL_PLUGINTYPE and PIL_PLUGIN *before* including this file. * * The way to use this stuff is to declare your primary entry point this way: * * This example is for an plugin of type "auth" named "sha1" * * #define PIL_PLUGINTYPE auth * #define PIL_PLUGIN sha1 * #include <upmls/PILPlugin.h> * * static const char* Ourpluginversion (void); * static const char* Ourpluginname (void); * static int Ourgetdebuglevel(void); * static void Oursetdebuglevel(int); * static void Ourclose (PILPlugin*); * * static struct PILPluginOps our_exported_plugin_operations = * { Ourpluginversion, * , Ourpluginname * , Ourgetdebuglevel * , Oursetdebuglevel * , Ourclose * }; * * static const PILPluginImports* PluginOps; * static PILPlugin* OurPlugin; * * // Our plugin initialization and registration function * // It gets called when the plugin gets loaded. * PIL_rc * PIL_PLUGIN_INIT(PILPlugin*us, const PILPluginImports* imports) * { * PluginOps = imports; * OurPlugin = us; * * // Register ourself as a plugin * / * imports->register_plugin(us, &our_exported_plugin_operations); * * // Register our interfaces * imports->register_interface(us, "interfacetype", "interfacename" * // Be sure and define "OurExports" and OurImports * // above... * , &OurExports * , &OurImports); * // Repeat for all interfaces in this plugin... * * } * * Except for the PIL_PLUGINTYPE and the PIL_PLUGIN definitions, and changing * the names of various static variables and functions, every single plugin is * set up pretty much the same way * *//* * No doubt there is a fancy preprocessor trick for avoiding these * duplications but I don't have time to figure it out. Patches are * being accepted... */#define mlINIT_FUNC _pil_plugin_init#define mlINIT_FUNC_STR "_pil_plugin_init"#define PIL_INSERT _LTX_#define PIL_INSERT_STR "_LTX_"/* * snprintf-style format string for initialization entry point name: * arguments are: (plugintype, pluginname) */#define PIL_FUNC_FMT "%s" PIL_INSERT_STR "%s" mlINIT_FUNC_STR#ifdef __STDC__# define EXPORTHELPER1(plugintype, insert, pluginname, function) \ plugintype##insert##pluginname##function#else# define EXPORTHELPER1(plugintype, insert, pluginname, function) \ plugintype/**/insert/**/pluginname/**/function#endif#define EXPORTHELPER2(a, b, c, d) EXPORTHELPER1(a, b, c, d)#define PIL_PLUGIN_INIT \ EXPORTHELPER2(PIL_PLUGINTYPE,PIL_INSERT,PIL_PLUGIN,mlINIT_FUNC)/* * Plugin loading return codes. OK will always be zero. * * There are many ways to fail, but only one kind of success ;-) */typedef enum { PIL_OK=0, /* Success */ PIL_INVAL=1, /* Invalid Parameters */ PIL_BADTYPE=2, /* Bad plugin/interface type */ PIL_EXIST=3, /* Duplicate Plugin/Interface name */ PIL_OOPS=4, /* Internal Error */ PIL_NOPLUGIN=5 /* No such plugin or Interface */}PIL_rc; /* Return code from Plugin fns*/const char * PIL_strerror(PIL_rc rc);typedef struct PILPluginImports_s PILPluginImports;typedef struct PILPluginOps_s PILPluginOps;typedef struct PILPlugin_s PILPlugin;typedef struct PILPluginUniv_s PILPluginUniv;typedef struct PILPluginType_s PILPluginType;typedef struct PILInterface_s PILInterface;typedef struct PILInterfaceImports_s PILInterfaceImports;typedef struct PILInterfaceUniv_s PILInterfaceUniv;typedef struct PILInterfaceType_s PILInterfaceType;typedef PIL_rc(*PILInterfaceFun)(PILInterface*, void* ud_interface);#define PIL_MAGIC_PLUGIN 0xFEEDBEEFUL#define PIL_MAGIC_PLUGINTYPE 0xFEEDCEEFUL#define PIL_MAGIC_PLUGINUNIV 0xFEEDDEEFUL#define PIL_MAGIC_INTERFACE 0xFEEDEEEFUL#define PIL_MAGIC_INTERFACETYPE 0xFEEDFEEFUL#define PIL_MAGIC_INTERFACEUNIV 0xFEED0EEFUL#define IS_PILPLUGIN(s) ((s)->MagicNum == PIL_MAGIC_PLUGIN)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -