Skip to content

Host side

Let’s now do a simple main function on the host side. We need to include the Pluma main header.
Let’s start by declaring an object of type Pluma (don’t forget that it’s in the pluma namespace):

pluma::Pluma manager;

We want to accept providers of type WarriorProvider only. Other kind of  providers that plug-ins try to register will be rejected. We do it this way:

manager.acceptProviderType< WarriorProvider >();

May look strange, but you can’t just pass the Type of a class as a function argument. That’s why we use a template argument instead.

To load a plugin we use the load function:

manager.load("plugins", "elite-warriors");

The first argument is the folder where to search for our plug-in. It may be a global path or relative to the program’s working directory.  The second argument is the plugin filename without extension.
Alternatively you can load all plug-ins from a folder:

pluma.loadFromFolder("plugins", true);

The second argument is optional. If true it will recursively load libraries from sub-folders.

Now we can access the loaded providers. We’ll put them in a vector of WarriorProvider pointers.

std::vector<WarriorProvider*> providers;
manager.getProviders(providers);

If we had other kind of providers we could get them using a vector of the respective type, getProviders always fill the vector with all providers of the type of the given vector. Also this function never clean the vector, it append providers to it’s end (for example for the case you already have some local providers in the vector).

Finally use the providers to create warriors. On our example let’s just create a warrior of each type and print it’s description:

std::vector<WarriorProvider*>::iterator it;
for (it = providers.begin() ; it != providers.end() ; ++it){
    Warrior* warrior = (*it)->create();
    std::cout << warrior->getDescription() << std::endl;
    delete warrior;
}

You can’t get rid of pointers here because of the polymorphism.
It should now compile. If the plug-in path is correct, the program should display the Eagle and Jaguar descriptions.

Conclusion

That’s all. We didn’t unloaded the plugin in the end because it’s automatically unloaded when the manager scope ends. Make sure that your manager is never destroyed while you’re using objects created from it’s providers. When the manager is destroyed, the application looses the access to the plugins code.

Finally note that the create function has no arguments. Plug-in classes must provide the default constructor only, which is used at the create function. Constructors with arguments can’t be used. If you need to initialize your objects with some data, the recommended way of doing it is by defining some init function on the shared interface, with the needed arguments. On the host side call that function right after an object creation. Eg:

Warrior* warrior = providers[0].create();
warrior->init(team, weapons);

But what if you really want to use other constructors? If you’re integrating Pluma with an existing project, do you have to convert every constructor in an init function? You don’t. Find out how on the next page.


Index || Plug-in Side << Host Side >>  Final Notes