You are not logged in.

#1 2018-03-28 20:06:37

lnxsurf
Member
Registered: 2014-05-28
Posts: 68

[SOLVED] C++ And Plugins

Hello,

I have question about C++ and plugins. How would you realize it?
For Linux distributions there are dlopen, dlsym functions available for shared objects (libraries). But that is C and not C++... Are there alternatives available for C++ or will it be available with C++20 (modules)?
By the way, I prefer to use LLVM and clang...

Thanks for your help...

Last edited by lnxsurf (2018-04-18 18:22:56)

Offline

#2 2018-03-28 20:29:08

progandy
Member
Registered: 2012-05-17
Posts: 5,190

Re: [SOLVED] C++ And Plugins

Using dlopen is the only way I know.
https://www.tldp.org/HOWTO/C++-dlopen/index.html

Edit: There are a few c++ plugin frameworks out there, you might want to search for one of them.

Last edited by progandy (2018-03-28 20:40:02)


| alias CUTF='LANG=en_XX.UTF-8@POSIX ' |

Offline

#3 2018-03-28 21:03:40

lnxsurf
Member
Registered: 2014-05-28
Posts: 68

Re: [SOLVED] C++ And Plugins

Hi,
thanks... so as I understand the name mangling is the problem and for that reason it should be used extern "C"? So it is just a name mangling thing?
Is that possible?

struct Foo {};
extern "C" std::unique_ptr<Foo> make_foo();

Offline

#4 2018-03-28 21:20:33

progandy
Member
Registered: 2012-05-17
Posts: 5,190

Re: [SOLVED] C++ And Plugins

name mangling is one of the problems. You cannot use new/delete directly either and need wrappers since instances that have been created by the plugin have to be deleted in the plugin and instances of the main application must not be deleted in the plugin.

This article has some good information as well:
https://www.codeproject.com/Articles/20 … in-Objects

Last edited by progandy (2018-03-28 21:22:18)


| alias CUTF='LANG=en_XX.UTF-8@POSIX ' |

Offline

#5 2018-04-08 19:34:41

hipersayan_x
Member
Registered: 2014-12-09
Posts: 36
Website

Re: [SOLVED] C++ And Plugins

C++ and C plugins are the exact same, it are defined as a dynamic library with public symbols you can load (functions and variables), libraries has not any concept of "objects" but you can export C++ objects as pointer to an instance, with a previously well defined common interface.
Then you start defining your interface, how do you define the interface depends on you, you can even define several interfaces depending on your needs, you can make them inherit from each other the extend them if you want.
You must also define an entry point pointer to create an instance of the interface.

plugininterface.h

#pragma once

// Define an abstract interface for the plugin.
class PluginInterface
{
    public:
        // Defining a virtual destructor make clang happy.
        virtual ~PluginInterface() {}

        virtual void sayHello() const = 0;
};

// Define a pointer type to the entry point.
typedef PluginInterface *(*PluginEntry)();

The plugin/library has not any idea what PluginInterface does internally, it has not idea it's an object, when loading the instance PluginInterface will just look like a type name.
Here PluginEntry is defined as a function returning a pointer to an instance of type PluginInterface, you can tweak it return any type of interface instance depending on your needs.
Then you define what you plugin instance will do.

plugin.cpp

// Compile with: clang++ -shared -fPIC -o plugin.so plugin.cpp

#include <iostream>

#include "plugininterface.h"

// Define the plugin interface.
class MyPlugin: public PluginInterface
{
    public:
        void sayHello() const
        {
            std::cout << "Hello from plugin!" << std::endl;
        }
};

// Define the entry point.
extern "C" PluginInterface *pluginEntry()
{
    return new MyPlugin;
}

You declare pluginEntry extern that way it will be public to the plugin loader.
And finally, you load the plugin to your program using dl functions.

pload.cpp

// Compile with: clang++ -o pload pload.cpp -ldl

#include <memory>
#include <dlfcn.h>

#include "plugininterface.h"

int main()
{
    // Load the plugin, you must specify the path otherwise it will try to load
    // the library from the system.
    auto plugin = dlopen("./plugin.so", RTLD_LAZY);

    // Load the entry point of the dynamic library.
    auto pluginEntry = reinterpret_cast<PluginEntry>(dlsym(plugin, "pluginEntry"));

    // Call entry point, and create an instance of plugin class.
    auto pluginInstance = std::shared_ptr<PluginInterface>(pluginEntry());

    // Use plugin instance as normal.
    pluginInstance->sayHello();

    // Close and unload plugin. The plugin must be unloaded once finished
    // otherwise you will cause a segfault.
    dlclose(plugin);

    return 0;
}

And here you have a basic boilerplate were you can start hacking from there. The same code can be compiled with both gcc and clang.

Offline

#6 2018-04-18 09:01:36

lnxsurf
Member
Registered: 2014-05-28
Posts: 68

Re: [SOLVED] C++ And Plugins

Hi,
Thanks a lot.
One point that I don t like is returning directly instances with the new operator.
Is that possible with smart pointers?

Offline

#7 2018-04-18 14:10:32

hipersayan_x
Member
Registered: 2014-12-09
Posts: 36
Website

Re: [SOLVED] C++ And Plugins

Well it seems possible, also changed the LAZY load for NOW | NODELETE.

plugininterface.h

#pragma once

#include <memory>

// Define an abstract interface for the plugin.
class PluginInterface
{
    public:
        // Defining a virtual destructor make clang happy.
        virtual ~PluginInterface() {}

        virtual void sayHello() const = 0;
};

typedef std::shared_ptr<PluginInterface> PluginInterfacePtr;

// Define a pointer type to the entry point.
typedef PluginInterfacePtr (*PluginEntry)();

plugin.cpp

// clang++ -shared -fPIC -o plugin.so plugin.cpp

#include <iostream>

#include "plugininterface.h"

// Define the plugin interface.
class MyPlugin: public PluginInterface
{
    public:
        void sayHello() const
        {
            std::cout << "Hello from plugin!" << std::endl;
        }
};

// Define the entry point.
extern "C" PluginInterfacePtr pluginEntry()
{
    return std::make_shared<MyPlugin>();
}

pload.cpp

// clang++ -o pload main.cpp -ldl

#include <memory>
#include <dlfcn.h>

#include "plugininterface.h"

int main()
{
    // Load the plugin, you must specify the path otherwise it will try to load
    // the library from the system.
    // RTLD_NOW will load all plugin symbols, RTLD_NODELETE will keep the
    // symbols loaded after close.
    auto plugin = dlopen("./plugin.so", RTLD_NOW | RTLD_NODELETE);

    // Load the entry point of the dynamic library.
    auto pluginEntry = reinterpret_cast<PluginEntry>(dlsym(plugin, "pluginEntry"));

    // Close the plugin.
    dlclose(plugin);

    // Call entry point, and create an instance of plugin class.
    auto pluginInstance = pluginEntry();

    // Use plugin instance as normal.
    pluginInstance->sayHello();

    return 0;
}

Offline

#8 2018-04-18 18:22:10

lnxsurf
Member
Registered: 2014-05-28
Posts: 68

Re: [SOLVED] C++ And Plugins

Nice!
It seems that works!

Do you know, if there will be any standardization about name mangling and the abi. For now I guess there is no compatibility between clang and gcc?

Offline

#9 2018-04-18 18:44:25

hipersayan_x
Member
Registered: 2014-12-09
Posts: 36
Website

Re: [SOLVED] C++ And Plugins

I don't think so, but you can try compiling the plugin with clang and the program with gcc and vice versa. I even tried compiling plugins with MinGW for programs in MSVC and it worked, clang and gcc are near cousins so it may not be any problem.

Offline

Board footer

Powered by FluxBB