如何在带DLL的应用程序中实现Singleton [英] How to implement a Singleton in an application with DLL
问题描述
我有一个包含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:
- 主要应用程序启动
- 第一个打印只是为了显示单身件尚未初始化
- 主应用程序初始化单身件
- 第一个打印显示初始化已正常工作
- 主应用程序启动硬件设备
- 没有初始化!我希望它输出
two = 2
- 最后的打印显示单例仍然在主应用程序中初始化
- Main application starts
- The first print is just to show that the singleton is not initialized yet
- Main application initializes the singleton
- The first print shows that the initialization worked
- Main application starts the "hardware device"
- Inside the DLL, the singleton is not initialized! I expect it to output
two = 2
- 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屋!