运行时动态加载和单例

时间:2017-09-13 08:54:11

标签: c++ singleton runtime shared-libraries dlopen

我有一个使用单例的程序。该程序在运行时加载共享库。该库也使用相同的单例。 问题是,当从库中访问单例时,会创建一个新的单例实例。

该程序与-rdynamic相关联,我同时使用-fPIC,加载如下:

std::shared_ptr<Module> createModuleObject(const std::string& filename)
{
    if (!fs::exists(filename))
        throw std::runtime_error("Library not found: " + std::string(filename));

    struct export_vtable* imports;
    void *handle = dlopen(filename.c_str(), RTLD_LAZY | RTLD_GLOBAL);

    if (handle) {
        imports = static_cast<export_vtable*>(dlsym(handle, "exports"));
        if (imports)
            return std::shared_ptr<Module>(imports->make());
        else 
            throw std::runtime_error("Error trying to find exported function in library!");
    } else
        throw std::runtime_error("Error trying to load library: " + std::string(filename));
}

该库导出一个这样的类:

Module* make_instance()
{
    return new HelloWorld();
}
struct export_vtable 
{
    Module* (*make)(void);
};
struct export_vtable exports = { make_instance };

并且该类使用单例。

这是单身人士的创建方式(Configuration.cpp):

std::unique_ptr<Configuration> Configuration::instance_(nullptr);
std::once_flag Configuration::onlyOnceFlag_;

Configuration& Configuration::instance()
{
    if (instance_ == nullptr)
    {
        std::cout << "INSTANCE IS NULL, CREATING NEW ONE" << std::endl;
        std::call_once(Configuration::onlyOnceFlag_,
                    [] {
                            Configuration::instance_.reset(new Configuration());
                       });
    }

    return *Configuration::instance_;
}    

程序和库都链接到Configuration.cpp。如果我从库中省略它,我在尝试访问单例时会收到一个未定义的符号错误。

任何人都知道如何解决这个问题?非常感谢你!

1 个答案:

答案 0 :(得分:0)

以下是我为https://github.com/kvahed/codeare/blob/master/src/core/ReconStrategy.hpp解决的问题 加载共享对象后,我将全局单例Workspace的实例分配给dll中的已加载类。 https://github.com/kvahed/codeare/tree/master/src/modules中的所有类都派生自ReconStrategy和共享对象。好的是这段代码是可移植的。

构建这样的ReconStrategy时会发生这种情况:

ReconContext::ReconContext (const char* name) {
    m_dlib = LoadModule ((char*)name);
  if (m_dlib) {
    create_t* create = (create_t*) GetFunction (m_dlib, (char*)"create");
    m_strategy = create();
    m_strategy->Name (name);
    m_strategy->WSpace (&Workspace::Instance());
    } else {
      m_strategy = 0;
    }
  }
}

这里的关键是m_strategy->WSpace (&Workspace::Instance());