How to manipulate / return data with dynamically loaded functions (dlopen)?

I spent days reading and re-reading every tutorial that I found on this subject, and spent hours (and even days) looking at related issues here at SO, but I still can't get the following to work. Please accept my apologies if this is a duplicate: it is likely that I saw and re-read the repeating questions many times, but could not understand the relevance of the answers to my problem. With this off the road ...

I am trying to implement a plugin architecture for my application. Plugins are compiled and installed in the form of libraries. At run time, the application then uses dlopen () / dlsym () to load and reference plugin functions.
The idea is that plugins (libraries) will implement a set of functions for returning data to the main application or manipulate data transferred from the application.

To test this idea, I tried to implement a function (inside the plugin) that would return the (readable) name of the module itself (like std :: string). I thought that from the very beginning there would be something simple ...: - /

Here is what I got so far:

// Plugin.cpp
extern "C" void plugin_name(std::string *name) {
        name = new std::string("Example plugin name");
}

// Application.cpp
void* handle = dlopen("libplugin.so", RTLD_LAZY);
typedef void (*plugin_t)(std::string*);
dlerror(); // Reset errors.
plugin_t call_plugin_name = (plugin_t) dlsym(handle, "plugin_name");
// ... Some error handling code.
std::string my_plugin_name;
call_plugin_name(&my_plugin_name);
dlclose(handle);
// More code that displays my_plugin_name.

I tried many different combinations, including one that seemed more stressful (but didn't work better), where the plugin name is returned:

// Plugin.cpp
extern "C" std::string plugin_name(void) {
        return std::string("Example plugin name");
}

, : ;)
, .

, , : plugin <= > Application. , "" std::string, (.. ). dlsym() , .

, ?

: , , , ? ?

+3
3

( ). extern "C", C, , -, ++, std::string. std::string .

, std::string . , .

++ , ++ . , C. ( - , )

- ++ . .

, , , . dynamic_cast , . , , .

[]

, .

, :

extern "C" const char * plugin_name() {
    return "Example plugin name";
}

// main.cc:
void* handle = dlopen("libplugin.so", RTLD_LAZY);
// ...
typedef const char * (*plugin_t)();
plugin_t call_plugin_name = (plugin_t) dlsym(handle, "plugin_name");
// ...
std::string my_plugin_name(call_plugin_name());
// use it

, :

// plugin.h
class Plugin {
    public:
        virtual void doStuff() = 0;
        virtual ~Plugin() = 0;
};

// plugin.cc
Plugin::~Plugin() {
}

// myplugin.cc
class MyPlugin : public Plugin {
    virtual void doStuff() {
        std::cout << "Hello from plugin" << std::endl;
    }
};

extern "C" Plugin *createMyPluginInstance() {
    return new MyPlugin;
}
+5

Try:

 extern "C" void plugin_name(std::string **name) {
     *name = new std::string("Example plugin name");
 }

 ...

 std::string *my_plugin_name;
 call_plugin_name(&my_plugin_name);

, , , .

EDIT : main.cpp

#include <iostream>
#include <dlfcn.h>
#include <string>

// Application.cpp
int main() {
    void* handle = dlopen("libplugin.so", RTLD_LAZY);
    typedef void (*plugin_t)(std::string**);
    dlerror(); // Reset errors.
    plugin_t call_plugin_name = (plugin_t) dlsym(handle, "plugin_name");
    // ... Some error handling code.
    std::string *my_plugin_name;
    call_plugin_name(&my_plugin_name);
    dlclose(handle);
    // More code that displays my_plugin_name.
    std::cout << "Plugin name is " << *my_plugin_name << std::endl;
    delete my_plugin_name;
    return 0;
}

plugin.cpp

#include <string>

extern "C" void plugin_name(std::string **name) {
    *name = new std::string("example plugin name");
}

. , ++ dll-boundry , , , . -.

+2

, . lib ++.

+1

Source: https://habr.com/ru/post/1785905/


All Articles