Skip to content

Chapter 2: Plugins and Modules

krogank9 edited this page May 10, 2018 · 15 revisions

When I was learning Ogre frame, the first concept I learned is the plugin, everything is the plugin in Ogre's world. The author of Ogre abstract the importance interface for Ogre frame, such as file management interface, render engine interface, and scene management interface. People can just implement that interface as a new plugin the replace the original plugin. For instance, people can use OpenGL plugin to replace D3D plugin in Ogre's world but do not need to restart the application.

In NoahGameFrame's world, a plugin is a container which organizes the modules, the class NFPluginManager manage all plugins and modules.

How to load the plugin?

In NoahGameFrame's world, all plugin's name will be saved in a file named "Plugin.XML" where locating at _Out/NFDataCfg/Debug or _Out/NFDataCfg/Release.

Let us see the example:

<XML>
    <GameServer>
        <Plugin Name="NFKernelPlugin" />
        <Plugin Name="NFConfigPlugin" />
        <Plugin Name="NFGameServerPlugin" />
        <Plugin Name="NFGameServerNet_ServerPlugin" />
        <Plugin Name="NFGameServerNet_ClientPlugin" />
        <Plugin Name="NFLogPlugin" />
        <ConfigPath Name="../" />		
    </GameServer>
</XML>

When we start the application with the args "-d Server=GameServer ID=3", the application will load the plugins from the GameServer section that show above. In this example there have 6 plugins: NFKernelPlugin, NFConfigPlugin, NFGameServerPlugin, NFGameServerNet_ServerPlugin, NFGameServerNet_ClientPlugin and NFLogPlugin.

The arg "-d" means the application running with daemon mode (Only supporting Linux/mac/Unix), the arg "ID=3" means the applications' ID as 3.

So, who will load those plugins?

Absolutely is class NFCPluginManager. The class NFCPluginManager is a single mode class in the application. When the application started, the class NFCPluginManager will be created and start to load the file "Plugin.xml" to load all plugins.

Below are the code:

int main(int argc, char* argv[])
{
    ProcessParameter(argc, argv);

    NFCPluginManager::GetSingletonPtr()->Awake();
    NFCPluginManager::GetSingletonPtr()->Init();
    NFCPluginManager::GetSingletonPtr()->AfterInit();
    NFCPluginManager::GetSingletonPtr()->CheckConfig();
    NFCPluginManager::GetSingletonPtr()->ReadyExecute();

    while (true)
    {
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
        NFCPluginManager::GetSingletonPtr()->Execute();
    }

    NFCPluginManager::GetSingletonPtr()->BeforeShut();
    NFCPluginManager::GetSingletonPtr()->Shut();

    NFCPluginManager::GetSingletonPtr()->ReleaseInstance();

    return 0;
}

The function LoadPluginConfig will be called in function NFCPluginManager::Awake(), the function LoadPluginConfig response for loading and parsing the XML file. After that, the class NFCPluginManager will create a plugin instance for each plugin.

How to add a new plugin and a new module?

In Linux(Mac), a plugin is a .so file, but in windows, it is a .dll file. If we want to create a new plugin in NoahGameFrame's world, we would copy the project from Tutorial1, it's the best easiest way to create a new plugin.

We can know from the Tutorial1 that the simplest plugin includes three classes, the one is a class inheritance NFIModule and the other two are the classes that inherit the class NFIplugin.

The codes are below:

class Tutorial1 : public NFIPlugin
{
public:
    Tutorial1(NFIPluginManager* p);

    virtual const int GetPluginVersion();

    virtual const std::string GetPluginName();

    virtual void Install()
    {
        REGISTER_MODULE(pPluginManager, NFIHelloWorld1, NFCHelloWorld1);
    }

    virtual void Uninstall();
};

NFIHelloWorld1: public NFIModule
{

};

class NFCHelloWorld1 : public NFIHelloWorld1
{
public:
    NFCHelloWorld1(NFIPluginManager* p);

    virtual bool Init();
    virtual bool AfterInit();

    virtual bool Execute();

    virtual bool BeforeShut();
    virtual bool Shut();

protected:

};

People who want to create an instance for one module, it's better to use the Macro REGISTER_MODULE to do this. By the way, if we want to use the other module we can find a module by their interface class's name, such as:

NFCHelloWorld1::AfterInit()
{
    m_pKernelModule = pPluginManager->FindModule<NFIKernelModule>();
    m_pHelloWorld1 = pPluginManager->FindModule<NFIHelloWorld1>();
};

Clone this wiki locally