Ogre插件简介

本来,打算写一下SampleBrowser范例的介绍的,但是觉得有必要在介绍OGRE代码之前先介绍一下OGRE插件机制的大致结构,毕竟OGRE里面插件机制设计的还是挺不错的,可以当做教科书般来学习,而且对以后代码的理解也有很多必要,所以在这里穿插一集,也让这个周末自己显得积极一些。好了,在一个简单的开场白之后我们进入主题,本章主要介绍的内容主要如下:

  • 动态库 
    动态库的一些基本知识
  • OGRE插件 
    OGRE插件的架构,实现机制

 

动态库简介

动态库&静态库

       无论是动态库还是静态库,都是用来存放一些公共函数的库文件,在代码的重用性上提供了很大的便捷,而两者之间的区别也很明显,下面给出一个简单的对比和个人经验

  区别 优缺点 备注
静态库 静态库则在编译期就将库内容打包到程序中,在程序运行时并不需要 独立性,兼容好 在最近移动设备,特别是Android的差异化和一些动态库数量的限制,静态库独立性,高兼容性的特点
动态库 运行时时调入,因此需要动态库的存在 灵活,体积小,重用度高 随着PC系统的标准化日益完善,目前的PC系统下静态库不如动态库常见

DLL&LIB

当我们编译完DLL后(Windows下),一般都会有一个同名字的lib文件,这个并不是静态库,我们可以理解这个对应DLL的配置文件,类似是一本书的目录,可以通过目录查询到这本书的某个函数或者某个类的位置。另外插一句,在Linux下只有so动态库,在脚本中-L就可以,没有lib文件照样玩得转,这个没有研究过。

  使用方式 备注
隐式链接 有三种方法:第一种是Dependence的方式,这适合有源码的方式,直接以来即可,不过这也是最弱的方式,会导致重复依赖等问题;第二种就是在VS工程里面添加lib文件,这个和makefile脚本的思路完全一样,第三种则是在头文件中添加#pragma comment(lib, “Lib.lib”) 使用简单,需要头文件和lib文件
显示链接 步骤只有两部:加载DLL的Handle,通过LoadLibrary、dlopen函数,获取指定全局函数的函数指针pFun,通过GetProcAddress、dlsym函数。OGRE插件简介中很详细介绍 不需要lib文件和头文件,这正好满足了插件的特点

OGRE插件简介

       一般情况下,插件加载主要有两种方式,一种是在Bin目录下面特定的后缀标识,在程序启动的时候自动加载,另外一种则是通过配置文件,将配置文件中指定的插件加载进来.而OGRE则是采用后者的方式.OGRE中涉及到插件的资源主要有两个plugins.cfg和samples_d.cfg,都放在bin目录下面,一个是OGRE工程所需要加载的插件,一个是范例所需要加载的SamplePlugin.

       OGRE插件的加载和管理主要由三大块来完成

  • Root 
    负责插件加载,管理的逻辑处理
  • DynLibManager 
    插件动态库Handle的加载
  • Plugin 
    插件基类外壳,所有插件的实体都继承自Plugin,达到实现的标准化

     

上图是OGRE插件加载的一个简单的逻辑过程,配合上面的流程图,简单说明一下:

  1. Root通过读取插件配置文件,加载具体指定的插件动态库,整个过程代码如下
       1: void Root::loadPlugin(const String& pluginName)
       2: {
       3:     // Load plugin library
       4:     DynLib* lib = DynLibManager::getSingleton().load( pluginName );
       5:     mPluginLibs.push_back(lib);
       6:     DLL_START_PLUGIN pFunc = (DLL_START_PLUGIN)lib->getSymbol("dllStartPlugin");
       7:     pFunc();
       8: }
  2. 动态库文件的加载
       1: #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
       2: #    define DYNLIB_HANDLE hInstance
       3: #    define DYNLIB_LOAD( a ) LoadLibraryEx( a, NULL, LOAD_WITH_ALTERED_SEARCH_PATH )
       4:  
       5: DynLib* DynLibManager::load( const String& filename)
       6: {
       7:     // 通过DynLib来load,最终获取该动态库的handle,DynLib只是一个封装的外壳
       8:     DynLib* pLib = OGRE_NEW DynLib(filename);
       9:     pLib->load();        
      10:     mLibList[filename] = pLib;
      11:     return pLib;
      12: }
      13:  
      14: void DynLib::load()
      15: {
      16:     //在Win下调用LoadLibraryEx来获取动态库handle 
      17:     m_hInst = (DYNLIB_HANDLE)DYNLIB_LOAD( name.c_str() );
      18: }
  3. OGRE中规定所有插件的动态库中都必须有一个全局函数命名为dllStartPlugin,此时已经获取DLL的handle,则通过该handle,获取该函数对应的函数指针 
       1: #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
       2: #    define DYNLIB_GETSYM( a, b ) GetProcAddress( a, b )
       3: #endif
       4: void* DynLib::getSymbol( const String& strName ) const throw()
       5: {
       6:     // 最终调用GetProcAddress获取dllStartPlugin函数指针
       7:     return (void*)DYNLIB_GETSYM( m_hInst, strName.c_str() );
       8: }
  4. 执行各自插件中的pFun函数,创建插件里面的具体类,实现具体功能,这里以RenderSystem_GL为例,创建OpenGL引擎后,调用installPlugin,将插件类的指针返回给Root进行维护管理
       1: extern "C" void _OgreGLExport dllStartPlugin(void) throw()
       2: {
       3:     plugin = new GLPlugin();
       4:     Root::getSingleton().installPlugin(plugin);
       5:  
       6: }
  5. 执行Root的installPlugin函数,完成整改插件的加载过程
       1: void Root::installPlugin(Plugin* plugin)
       2: {
       3:     // 假如插件列表进行管理
       4:     mPlugins.push_back(plugin);
       5:     // 插件类执行函数,完成自己的特定功能
       6:     plugin->install();
       7: }

如上,一个插件的加载过程基本结束,而Root类中分别由mPluginLibs和mPlugins来维护动态库handle和插件类的指针,通过插件来完成个性化的功能。

总结OGRE的插件方式,个人觉得做的非常优秀,虽然不复杂,但是非常的标准,条理清晰,而且难得可贵的是Plugin和DynLib、DynLibManager三个类,约束了插件的行为,使得整个插件都统一化,遵循标准的虚函数来实现自己,这样,随着类库的丰富和扩展,不会导致五花八门的插件泛滥。这种插件结构很成熟,也可以是我们以后开发程序时可以借鉴的架构方式。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值