http://www.cnblogs.com/pulas/archive/2012/02/18/2357663.html
http://www.cnblogs.com/pulas/archive/2012/02/18/2357663.html
Ogre的插件可以是动态链接库,也可以是静态链接库。若是动态链接库,则可通过在插件配置文件(默认为plugins.cfg)里添加插件名称,然后在创建Root时,会在Root的构造函数里通过Root::loadPlugin(const String& pluginName)方法遍历加载每一个插件。也可通过Root::loadPlugin(const String& pluginName)方法手动加载自定义插件。
当Root::loadPlugin(const String& pluginName)函数被调用时,Ogre将加载该插件的dll,并从中查找并调用名为dllStartPlugin()的导出函数。对应的,当Root::unloadPlugin(const String& pluginName)函数被调用时,Ogre将从该dll中调用dllStopPlugin()函数,并将该dll卸载。所以每个插件在实现的时候,都必须提供上述的两个C导出函数。其中,dllStartPlugin()负责创建插件实例,并调用Root::installPlugin(),将创建好的插件指针传递给Root对象。在这里,dllStartPlugin()实际可以创建多个插件实例,并依次调用Root::installPlugin(),这样我们就可以在一个dll中包含多个插件了。在dllStopPlugin()时,则需要调用 Root::uninstallPlugin(),并将插件dll中创建的plugin实例释放掉。所以,若要实现一个四叉树的场景管理器插件,则必须先实现这两个C导出函数。
#include <OgreRoot.h>
#include <QuadtreePlugin.h>
#ifndef OGRE_STATIC_LIB
namespace Ogre
{
QuadtreePlugin* quadtreePlugin;
extern "C" void _QuadtreePluginExport dllStartPlugin( void )
{
// Create new scene manager
quadtreePlugin = OGRE_NEW QuadtreePlugin();
// Register
Root::getSingleton().installPlugin(quadtreePlugin);
}
extern "C" void _QuadtreePluginExport dllStopPlugin( void )
{
Root::getSingleton().uninstallPlugin(quadtreePlugin);
OGRE_DELETE quadtreePlugin;
}
}
#endif
在上述dllStartPlugin( void )函数中创建自定义插件。Ogre定义了一个抽象的Plugin插件接口,每一个插件都必须实现该插件接口。
class _OgreExport Plugin : public PluginAlloc
{
public:
Plugin() {}
virtual ~Plugin() {}
/** Get the name of the plugin.
@remarks An implementation must be supplied for this method to uniquely
identify the plugin.
*/
virtual const String& getName() const = 0;
/** Perform the plugin initial installation sequence.
@remarks An implementation must be supplied for this method. It must perform
the startup tasks necessary to install any rendersystem customisations
or anything else that is not dependent on system initialisation, ie
only dependent on the core of Ogre. It must not perform any
operations that would create rendersystem-specific objects at this stage,
that should be done in initialise().
*/
virtual void install() = 0;
/** Perform any tasks the plugin needs to perform on full system
initialisation.
@remarks An implementation must be supplied for this method. It is called
just after the system is fully initialised (either after Root::initialise
if a window is created then, or after the first window is created)
and therefore all rendersystem functionality is available at this
time. You can use this hook to create any resources which are
dependent on a rendersystem or have rendersystem-specific implementations.
*/
virtual void initialise() = 0;
/** Perform any tasks the plugin needs to perform when the system is shut down.
@remarks An implementation must be supplied for this method.
This method is called just before key parts of the system are unloaded,
such as rendersystems being shut down. You should use this hook to free up
resources and decouple custom objects from the OGRE system, whilst all the
instances of other plugins (e.g. rendersystems) still exist.
*/
virtual void shutdown() = 0;
/** Perform the final plugin uninstallation sequence.
@remarks An implementation must be supplied for this method. It must perform
the cleanup tasks which haven't already been performed in shutdown()
(e.g. final deletion of custom instances, if you kept them around incase
the system was reinitialised). At this stage you cannot be sure what other
plugins are still loaded or active. It must therefore not perform any
operations that would reference any rendersystem-specific objects - those
should have been sorted out in the 'shutdown' method.
*/
virtual void uninstall() = 0;
};
Root::getSingleton().installPlugin(plugin)会负责调用插件的install()操作,并将插件的指针存放起来,以备卸载时使用。Root::initialise()会负责调用插件的initialise()操作。
Plugin::install()以及Plugin::initialise()则分别负责创建OgreMain提供扩展功能接口的实例,以及将创建好的对象挂载到应用程序当中。
Root:: shutdown()会负责调用插件的shutdown()操作。Root::getSingleton().uninstallPlugin(plugin)会负责调用插件的uninstall()操作。
使用插件时几个需要注意的地方:
1. 调用插件DLL方法创建的对象需要交由插件DLL释放。(因为不同的链接单元可能具有不同的内存管理上下文环境,此处的new与彼处的new在语义上未必等同)
2. 调用插件DLL方法获取的插件内对象的引用或指针,在插件DLL卸载之后就是无效的,必须保证不再使用。(比较容易引发问题的一个典型例子是从插件中传递回一个引用计数字符串,当DLL被卸载后,字符串内指向实际数据的指针已经无效,但是在该对象析构时,仍需要访问该指针)
若插件是静态链接库,则可在任何时候创建插件,然后在创建Root后,调用Root::installPlugin(plugin)安装插件。手动调用Root::uninstallPlugin(plugin)卸载插件