Cpper
C/C++高级工程师 Android高级软件工程师 IT集成工程师 音频工程师 熟悉c,c++,java,c#,py,js,asp等多种语言 程序猿
插件系统是游戏引擎中一个比较大的子系统
这个系统的目的就是动态增加引擎的功能而不必修改引擎接口

之前虽然做过插件这块‘
但是感觉设计的不好
这次总算弄了一个比较完备的插件系统

相关对象和结构
1.插件 Plugin
///////////////////////////////////////////////////////////
/// 定义引擎插件数据结构
///////////////////////////////////////////////////////////
class Plugin
{
public:
    Plugin()
    {   
        Reset();
    }   
    
///////////////////////////////////////////////////////
    
/// 插件重启
    
///////////////////////////////////////////////////////     
    void Reset();
    
///////////////////////////////////////////////////////
    
/// 插件名字
    
///////////////////////////////////////////////////////     
    engine_string name;
    
///////////////////////////////////////////////////////
    
/// 插件作者
    
///////////////////////////////////////////////////////     
    engine_string maker;
    
///////////////////////////////////////////////////////
    
///插件描述
    
///////////////////////////////////////////////////////     
    engine_string description;
    
///////////////////////////////////////////////////////
    
/// 插件版本
    
///////////////////////////////////////////////////////     
    ushort  vermain;
    
ushort  versub;
    
ushort  verpitch;
    
///////////////////////////////////////////////////////
    
/// 插件类型
    
///////////////////////////////////////////////////////     
    ushort  type;
    
///////////////////////////////////////////////////////
    
/// 插件合法性标记
    
///////////////////////////////////////////////////////     
    ushort  valid;
};
插件数据结构只包含了插件的一些基本信息 比如名字,描述,作者,功能类型等

2.PluginLoader
////////////////////////////////////////////////////////
/// 定义插件载入类
////////////////////////////////////////////////////////
class PluginLoader
{
public:
    
/////////////////////////////////////////////////////
    
/// 构造,析构插件载入
    
/////////////////////////////////////////////////////
    PluginLoader();
    
~PluginLoader();
public:     
    
/////////////////////////////////////////////////////
    
/// 载入插件和卸载
    
/////////////////////////////////////////////////////
    bool  Load(const engine_string &plugin);
    
void  Free();     
    
/////////////////////////////////////////////////////
    
/// 获取插件指定符号地址
    
/////////////////////////////////////////////////////     
    void* GetAddress(const engine_string &name);
    
/////////////////////////////////////////////////////
    
/// 检测插件是否合法
    
/////////////////////////////////////////////////////     
    bool  IsValid()const{return handle != NULL;}
    
/////////////////////////////////////////////////////
    
/// 获取插件句柄
    
/////////////////////////////////////////////////////
    void* GetHandle(){return handle;}
    
void* GetHandle()const{return handle;}   
    
/////////////////////////////////////////////////////
    
/// 获取插件名
    
/////////////////////////////////////////////////////
    engine_string GetPluginName()const{return pluginame;}   
private:     
    
void*         handle;
    engine_string pluginame;   
};

PluginLoader主要是载入插件文件并获取给定符号的函数指针
这个并没没有暴漏出来供用户调用
3.PluginFactory

///////////////////////////////////////////////////////////
/// 定义引擎插件工厂基类
///////////////////////////////////////////////////////////
class GAPI PluginFactory : public Object
{
public:
    
///////////////////////////////////////////////////////
    
/// 构造和析构引擎插件工厂基类
    
///////////////////////////////////////////////////////
    PluginFactory();
    
virtual ~PluginFactory();
public:
    
///////////////////////////////////////////////////////
    
/// 注册,反注册插件
    
///////////////////////////////////////////////////////
    virtual bool ENGINE_CALL RegisterFactory(const engine_string& plugin) = 0;
    
virtual void ENGINE_CALL UnregisterFacory() = 0;
public:     
    
///////////////////////////////////////////////////////
    
/// 获取对应插件类型标识
    
///////////////////////////////////////////////////////     
    virtual ushort GetPluginType()const = 0;
private:
    DECLARE_OBJECT(PluginFactory)        
};

插件工厂是一切需要从插件中获取功能的对象工厂
她主要提供了插件的注册和反注册以及获取插件工厂所对应的插件类型

4.PluginManager 插件管理器
///////////////////////////////////////////////////////////
/// 定义引擎插件管理器
///////////////////////////////////////////////////////////
class GAPI PluginManager
{   
public:
    
///////////////////////////////////////////////////////
    
/// 获取,设置插件目录
    
///////////////////////////////////////////////////////
    engine_string GetPluginFolder()const;
    
void SetPluginFolder(const engine_string& folder);
public:
    
///////////////////////////////////////////////////////
    
/// 插件装载和卸载
    
///////////////////////////////////////////////////////
    void InstallPlugin();   
    
void UnstallPlugin();   
public:
    
///////////////////////////////////////////////////////
    
/// 注册,反注册插件工厂
    
///////////////////////////////////////////////////////        
    bool RegisterPluginFactory(PluginFactory* factory);
    
bool UnregisterPluginFactory(PluginFactory* factory);
public:
    
///////////////////////////////////////////////////////
    
/// 获取插件个数
    
///////////////////////////////////////////////////////        
    ushort ENGINE_CALL GetPluginNumber()const;
    
///////////////////////////////////////////////////////
    
/// 获取给定索引插件信息
    
///////////////////////////////////////////////////////
    Plugin ENGINE_CALL GetPluginByType(ushort index)const;
    
///////////////////////////////////////////////////////
    
/// 获取给定索引的插件名
    
///////////////////////////////////////////////////////  
    engine_string ENGINE_CALL GetPluginNameByType(ushort index)const;   
    
///////////////////////////////////////////////////////
    
/// 获取给定插件类型的插件载入类
    
///////////////////////////////////////////////////////      
private:
    PluginManagerImpl  
*impl;
    DEFINE_SINGLETON(PluginManager);
};

}

//! 定义插件管理器单件
#define GLOBAL_PLUGINMANAGER_PTR (core::PluginManager::GetInstance())
插件管理器是插件系统的核心,充当了插件管理者的角色
要使用插件线需要设置插件目录
然后装载插件
然后注册特定的插件工厂
然后就可以通过插件工厂获取插件对象指针咯

在这里插件管理器是作为一个单间使用的
具体的宏 DEFINE_SINGLETON(PluginManager);
展开之后为:
#define DEFINE_SINGLETON(SingletonObject)\
private:\
    
static std::auto_ptr<SingletonObject> instance;\
protected:\
    SingletonObject();\
public:\
    
~SingletonObject();\
    
static SingletonObject* GetInstance(){\
    
if(!instance.get())\
    {\
        instance 
= std::auto_ptr<SingletonObject>(new SingletonObject());\
    }\
    
return instance.get();\
}

#define IMPLEMENT_SINGLETON(SingletonObject)\
std::auto_ptr
<SingletonObject> SingletonObject::instance(NULL);
下面是具体的一个插件对象---摄像头捕获类
如下:通过调用CaptureImage就可以把摄像头所见程序保存为image了
///////////////////////////////////////////////////////////
/// 定义摄像头捕获类(以插件形式提供之)
///////////////////////////////////////////////////////////
class GAPI CapturePicture : public Object
{
public:
    
///////////////////////////////////////////////////////
    
/// 构造和析构
    
///////////////////////////////////////////////////////
    CapturePicture();
    
virtual ~CapturePicture();
public:
    
///////////////////////////////////////////////////////
    
/// 获取摄像头图形数据
    
///////////////////////////////////////////////////////
    virtual bool CaptureImage(RefPtr<Image> &image);
private:
    DECLARE_OBJECT(CapturePicture)        
};

通过调用CaptureImage就可以把摄像头所见程序保存为image了

下面这个是对于的工厂:
///////////////////////////////////////////////////////////
/// 定义摄像头捕获工厂类
///////////////////////////////////////////////////////////
class GAPI CapturePictureFactory : public PluginFactory
{
public:
    
///////////////////////////////////////////////////////
    
/// 构造和析构
    
///////////////////////////////////////////////////////
    CapturePictureFactory();
    
virtual ~CapturePictureFactory();
public:
    
///////////////////////////////////////////////////////
    
/// 获取摄像头捕获指针
    
///////////////////////////////////////////////////////
    CapturePicture* Create();
    
///////////////////////////////////////////////////////
    
/// 注册插件
    
///////////////////////////////////////////////////////
    bool ENGINE_CALL RegisterFactory(const engine_string& plugin);
    
void ENGINE_CALL UnregisterFacory();
    
///////////////////////////////////////////////////////
    
/// 获取对应插件类型标识
    
///////////////////////////////////////////////////////     
    ushort GetPluginType()const;
private:
    PluginLoader
* loader;
    DECLARE_OBJECT(CapturePictureFactory)
};
这个只是多了一个函数Createer而已

然后再说具体的插件部分
插件3函数:
extern "C" void    GAPI Plugin_Info(Plugin &plugin);         
extern "C" Object* GAPI Plugin_Install();
extern "C" void    GAPI Plugin_Unstall(void*);  
具体为通过Plugin_Info
通过Plugin_Install获取插件实际对象指针
通过Plugin_Unstall卸载插件

最后一个部分是插件的使用小例子:
#include <cstdlib>
#include 
<iostream>
#include 
<GEngine/Header.hpp>

using namespace std;

int main(int argc, char *argv[])
{
    GLOBAL_PLUGINMANAGER_PTR
->SetPluginFolder("plugin");
    GLOBAL_PLUGINMANAGER_PTR
->InstallPlugin();
    std::cout
<<"插件个数:"<<GLOBAL_PLUGINMANAGER_PTR->GetPluginNumber()<<std::endl;
    core::CapturePictureFactory factory;
  &nb$L̪ԌE$L̪Ԍspan style="color: #000000;"><<
"注册视频捕获插件工厂:"<<GLOBAL_PLUGINMANAGER_PTR->RegisterPluginFactory(&factory)<<std::endl;
    core::CapturePicture
* capturepicture = factory.Create();
    std::cout
<<"插件工厂产品标识:"<<factory.GetPluginType()<<std::endl;
    core::RefPtr
<core::Device> device = core::InitDevice("插件测试");
    
if(!capturepicture)
    {
        std::cout
<<"生成摄像头捕获指针失败了"<<std::endl;
        system(
"PAUSE");
        
return -1;
    }
    core::RefPtr
<core::ResourceManager> resmgr = device->GetResourceManager();
    core::RefPtr
<core::ImageManager> imagemanager = resmgr->GetImageManager();
    core::RefPtr
<core::Image> image = imagemanager->CreateObject("capturepicture");
   
    capturepicture
->CaptureImage(image);
    std::cout
<<"save image is:"<<image->Save("capture.bmp")<<std::endl;
   
    BEGIN_LOOP(device)
       glClearColor(
0.1,0.3,0.2,1.0f);
       glClear(GL_COLOR_BUFFER_BIT 
| GL_DEPTH_BUFFER_BIT);     
    END_LOOP(device)   
   
    GLOBAL_PLUGINMANAGER_PTR
->UnregisterPluginFactory(&factory);
    GLOBAL_PLUGINMANAGER_PTR
->UnstallPlugin();
    
//system("PAUSE");
    return EXIT_SUCCESS;
}
题后话:
当前引擎支持xp,vista,win7环境
在编译器支持vc7.1,vc8,vc9,devc++,codeblock
也许在不久的将来我会弄一个linux版本的
posted on 2010-07-29 16:40 ccsdu2009 阅读(2091) 评论(17)  编辑 收藏 引用 所属分类: Game引擎
Comments
  • # re: 盖莫游戏引擎-插件系统
    ccsdu2009
    Posted @ 2010-07-29 16:41
    有问题的话 请同志们指针  回复  更多评论   
  • # re: 盖莫游戏引擎-插件系统
    路青飞
    Posted @ 2010-07-29 17:09
    看起来不错,等我把王爽老师的汇编语言看完了,学习一下你的引擎。  回复  更多评论   
  • # re: 盖莫游戏引擎-插件系统
    ccsdu2009
    Posted @ 2010-07-29 18:50
    @路青飞
    谢谢支持  回复  更多评论   
  • # re: 盖莫游戏引擎-插件系统
    ccsdu2009
    Posted @ 2010-07-29 18:55
    @路青飞
    @路青飞
    有问题请教你汇编问题啊 呵呵我不懂  回复  更多评论   
  • # re: 盖莫游戏引擎-插件系统
    issingle@gmail.com
    Posted @ 2010-07-30 09:24
    插件系统中,最关键和最难点是插件之间的通信.  回复  更多评论   
  • # re: 盖莫游戏引擎-插件系统
    napolen
    Posted @ 2010-07-30 10:30
    我觉得你这背景应该改一下,看文章看起来太别扭了。  回复  更多评论   
  • # re: 盖莫游戏引擎-插件系统[未登录]
    ccsdu2009
    Posted @ 2010-07-30 10:48
    @issingle@gmail.com
    这个不是当前的问题
    我做东西喜欢循序渐进
      回复  更多评论   
  • # re: 盖莫游戏引擎-插件系统
    Husiwa
    Posted @ 2010-08-02 16:13
    这个,貌似不能够自动检测到有多少插件吧?
    我的意思是,用户写个插件,放到你的插件目录下,
    PluginManager能够自动检测出来吗?  回复  更多评论   
  • # re: 盖莫游戏引擎-插件系统
    ccsdu2009
    Posted @ 2010-08-02 16:46
    @Husiwa

    但是要按照给定插件格式写  回复  更多评论   
  • # re: 盖莫游戏引擎-插件系统
    Husiwa
    Posted @ 2010-08-03 10:53
    @ccsdu2009
    哦,上面的代码貌似没有体现出这一点。  回复  更多评论   
  • # re: 盖莫游戏引擎-插件系统
    ccsdu2004
    Posted @ 2010-08-03 10:56
    @Husiwa
    ///////////////////////////////////////////////////////
    /// 获取插件个数
    ///////////////////////////////////////////////////////
    ushort ENGINE_CALL GetPluginNumber()const;  回复  更多评论   
  • # re: 盖莫游戏引擎-插件系统
    Husiwa
    Posted @ 2010-08-04 18:14
    @ccsdu2004
    哦,这样,看的不仔细,不好意思。
    这样的话,是否需要配置文件呢?
    C#可以通过反射机制来获取插件信息,C++呢?  回复  更多评论   
  • # re: 盖莫游戏引擎-插件系统
    ccsdu2009
    Posted @ 2010-08-04 20:41
    @Husiwa
    可以通过载入插件来获取插件信息  回复  更多评论   
  • # re: 盖莫游戏引擎-插件系统

    Posted @ 2010-08-08 01:44
    最近在研究插件系统, 能否提供例子代码下载???  回复  更多评论   
  • # re: 盖莫游戏引擎-插件系统
    BoYue
    Posted @ 2010-08-08 13:48
    @Husiwa
    可以通过配置文件,也可以通过搜索插件的接口名来确定有哪些插件. 把多个插件的DLL放在目录下.然后搜索这些DLL,用GetProcAddress即可确定哪些是插件.   回复  更多评论   
  • # re: 盖莫游戏引擎-插件系统
    ccsdu2009
    Posted @ 2010-08-08 16:16
    @杨
    过段时间吧 O(∩_∩)O~  回复  更多评论   
  • # re: 盖莫游戏引擎-插件系统

    Posted @ 2010-08-12 10:10
    谢谢,等你。  回复  更多评论   

只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理