如何在带DLL的应用程序中实现Singleton [英] How to implement a Singleton in an application with DLL

查看:117
本文介绍了如何在带DLL的应用程序中实现Singleton的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个包含3个项目的应用程序(在MS Visual Studio中):

I have an application (in MS Visual Studio) that contains 3 projects:


  • main 包含 main 函数)

  • 设备(模拟某些硬件设备)

  • config (包含其他项目的一些配置)

  • main (the one that contains the main function)
  • device (models some hardware device)
  • config (contains some configuration for both other projects)

is:


  • 取决于设备
  • 取决于配置

  • main depends on device, which depends on config
  • main depends on config

config 项目包含一个Singleton,其中包含一些配置参数。

The config project contains a Singleton, which holds some configuration parameters.

我决定将设备项目导入DLL。当我这样做,似乎我在配置项目中有Singleton的两个实例!我想这是一个经典的问题,这可能有一个很好的解决方案。那么我该如何解决这个问题?

I decided to turn the device project into a DLL. When i did this, it seems that i got two instances of the Singleton in the config project! I guess this is a classic problem, which might have a good solution. So how can i fix this?

我重现了下面(相对较小的)代码的问题。当然,在我的情况下,有大约30个项目,不只是3.我想只使一个DLL(如果可能)。

I reproduced the problem with the following (relatively small) code. Of course, in my case there are some 30 projects, not just 3. And i would like to make just 1 DLL (if possible).

// config.h
#pragma once
#include <string>
#include <map>
class Config
{
public:
    static void Initialize();
    static int GetConfig(const std::string& name);

private:
    std::map<std::string, int> data;
};

// config.cpp
#include "config.h"

static Config g_instance;

void Config::Initialize()
{
    g_instance.data["one"] = 1;
    g_instance.data["two"] = 2;
}

int Config::GetConfig(const std::string& name)
{
    return g_instance.data[name];
}







// device.h
#pragma once

#ifdef _DLL
#define dll_cruft __declspec( dllexport )
#else
#define dll_cruft __declspec( dllimport )
#endif

class dll_cruft Device
{
public:
    void Work();
};

// device.cpp
#include "device.h"
#include <iostream>
#include "config.h"

void Device::Work()
{
    std::cout << "Device is working: two = " << Config::GetConfig("two") << '\n';
}







// main.cpp
#include <iostream>
#include "config.h"
#include "device.h"

int main()
{
    std::cout << "Before initialization in application: one = " << Config::GetConfig("one") << '\n';
    Config::Initialize();
    std::cout << "After initialization in application: one = " << Config::GetConfig("one") << '\n';
    Device().Work();
    std::cout << "After working in application: two = " << Config::GetConfig("two") << '\n';
}






输出:


Output:


在应用程序初始化之前:one = 0

Before initialization in application: one = 0

在应用程序初始化后:one = 1

After initialization in application: one = 1

设备正在工作:two = 0

Device is working: two = 0

在应用程序中工作后:two = 2

After working in application: two = 2

有关代码的作用及原因的一些说明:

Some explanations on what the code does and why:


  1. 主要应用程序启动

  2. 第一个打印只是为了显示单身件尚未初始化

  3. 主应用程序初始化单身件

  4. 第一个打印显示初始化已正常工作

  5. 主应用程序启动硬件设备

  6. 没有初始化!我希望它输出 two = 2

  7. 最后的打印显示单例仍然在主应用程序中初始化

  1. Main application starts
  2. The first print is just to show that the singleton is not initialized yet
  3. Main application initializes the singleton
  4. The first print shows that the initialization worked
  5. Main application starts the "hardware device"
  6. Inside the DLL, the singleton is not initialized! I expect it to output two = 2
  7. The last print shows that the singleton is still initialized in main application


推荐答案

您可以决定单身应该居住在哪里,然后将其公开给其他消费者。

You can decide where singleton should reside and then expose it to other consumers.

由OP编辑:

例如,我想要 config 实例只出现在EXE(不是DLL)中。

For example, i want that the config instance appear only in the EXE (not DLL).


    <
static Config* g_instance;


  • 设备添加单独的初始化函数的导出函数:

    void InitializeWithExisting(Config* instance) {g_instance=instance;}
    


  • 正常初始化单例后,使用第二个初始化:

  • After initializing the singleton normally, use the second initialization:

    Config::Initialize();
    Config::InitializeWithExisting();
    


  • 这篇关于如何在带DLL的应用程序中实现Singleton的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆