C++ and dynamically loaded libraries having derived classes

Documentation
Login

Documentation

#include <dlfcn.h>  // dlload, dlsym, dlclose

#include <iostream>
#include <memory>
#include <unordered_map>
#include <utility>
#include <vector>

#include "smart_manager.h"

int main(int argc, char* argv[]) {
    PluginManager pm;
    // const std::vector<std::string> plugin_names = {"foo", "bar", "baz"};
    (void)argc;
    (void)argv;
    std::cout << "Hello, smart3 demo!" << std::endl;

    // Create a foo instance
    std::string name = "foo";
    // Log my_log("MY FOO LOG PREFIX: ");
    // Don't make the Log object a unique_ptr, as we may want to share the same object among different plugin instances
    // auto my_log = std::make_unique<Log>("MY FOO LOG PREFIX: ");
    // Plugin::Params params = {std::move(my_log)}; // 'move' is required for unique_ptr
    auto my_log = std::make_shared<Log>("MY FOO LOG PREFIX: ");
    Plugin::Params params = {my_log};
    auto foo = pm.CreatePluginInstance(name, params);
    if (!foo) {
        std::cerr << "ERROR: Could not get first instance of 'foo'!\n";
        return 1;
    }
    foo->Init();

    // Create a second foo instance
    // Log my_log2("MY SECOND INSTANCE OF FOO LOG PREFIX: ");
    // auto my_log2 = std::make_unique<Log>("MY SECOND INSTANCE OF FOO LOG PREFIX: ");
    // params = {std::move(my_log2)};
    auto my_log2 = std::make_shared<Log>("MY SECOND INSTANCE OF FOO LOG PREFIX: ");
    params = {my_log2};
    auto foo2 = pm.CreatePluginInstance(name, params);
    if (!foo2) {
        std::cerr << "ERROR: Could not get second instance of 'foo'!\n";
        return 1;
    }
    foo2->Init();

    // Create a bar instance
    name = "bar";
    // Log my_log3("MY BAR LOG PREFIX: ");
    // auto my_log3 = std::make_unique<Log>("MY GENERIC PLUGIN LOG PREFIX: ");
    // Plugin::Params params3 = {std::move(my_log3)};
    // By moving this unique_ptr, it cannot be reused by baz (see below)
    auto my_log3 = std::make_shared<Log>("MY GENERIC PLUGIN LOG PREFIX: ");
    Plugin::Params params3 = {my_log3};
    auto bar = pm.CreatePluginInstance(name, params3);
    if (!bar) {
        std::cerr << "ERROR: Could not get instance of 'bar'!\n";
        return 1;
    }
    bar->Init();

    // Create a baz instance
    name = "baz";
    // Log my_log4("MY BAZ LOG PREFIX: ");
    // auto my_log4 = std::make_unique<Log>("MY BAZ LOG PREFIX: ");
    // Trying to use an already moved unique_ptr results in a nullptr
    // Plugin::Params params4 = {std::move(my_log3)};
    // Plugin::Params params4 = {std::move(my_log3)};
    Plugin::Params params4 = {my_log3};
    auto baz = pm.CreatePluginInstance(name, params4);
    if (!baz) {
        std::cerr << "ERROR: Could not get instance of 'bar'!\n";
        return 1;
    }
    baz->Init();

    // Cleanup plugins
    foo->Cleanup();
    foo2->Cleanup();
    bar->Cleanup();
    baz->Cleanup();

    return 0;
}