如何在具有 DLL 的应用程序中实现单一实例
How to implement a Singleton in an application with DLL
我有一个应用程序(在MS Visual Studio中(,其中包含3个项目:
-
main(包含
main
函数的那个(
设备 - (型号某些硬件设备(
- config(包含其他两个项目的一些配置(
所以依赖关系图是:
- 主要取决于设备,这取决于配置
- 主要取决于配置
项目包含一个单一实例,其中包含一些配置参数。
我决定将设备项目转换为 DLL。当我这样做时,似乎我在配置项目中得到了两个单例实例!我想这是一个经典的问题,可能有一个很好的解决方案。那么我该如何解决这个问题呢?
我用以下(相对较小的(代码重现了这个问题。当然,就我而言,大约有30个项目,而不仅仅是3个。我只想制作 1 个 DLL(如果可能的话(。
// 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';
}
输出:
在应用程序中初始化之前:1 = 0
在应用程序中初始化后:1 = 1
设备工作:2 = 0
在应用程序中工作后:2 = 2
关于代码的作用和原因的一些解释:
- 主应用程序启动
- 第一次打印只是为了表明单例尚未初始化
- 主应用程序初始化单例
- 第一次打印显示初始化有效
- 主应用启动"硬件设备">
- 在 DLL 内部,未初始化单一实例!我希望它能输出
two = 2
- 最后一次打印显示单例仍在主应用程序中初始化
当我遇到同样的问题时,我通过创建另一个 DLL 来解决它,其唯一目的是管理单一实例。获取指向单一实例的指针的所有尝试都会调用此新 DLL 中的函数。
您可以决定单例应驻留的位置,然后将其公开给其他使用者。
OP编辑:
例如,我希望config
实例仅出现在 EXE(而不是 DLL(中。
-
将实例转换为指针
static Config* g_instance;
-
向
device
导出的函数添加单独的初始化函数:void InitializeWithExisting(Config* instance) {g_instance=instance;}
-
正常初始化单例后,使用第二次初始化:
Config::Initialize(); Config::InitializeWithExisting();
我相信
以这种方式定义和访问单例实例可能会解决您的问题:
Config& getInstance()
{
static Config config;
return config;
}
这样,您也不需要拥有(和调用(Initialize 方法,您可以使用构造函数进行初始化,当您第一次调用 getInstance 时将自动调用该方法。
相关文章:
- 如何为模块化应用程序实现C++插件系统
- 如何使用winsock在c++应用程序中实现安全套接字通信
- 在 MFC 应用程序中实现 IServiceProvider
- 如何在 2 个应用程序之间实现拖放?
- 内部源代码 - 在链接列表实现中插入元素上的删除会破坏整个应用程序
- 在已经运行的C 控制台应用程序上实现QT GUI
- 如何实现MATLAB和单独的C++应用程序之间的通信
- MVC:命令行应用程序的实现问题
- windows应用程序中的键盘类实现
- 在主应用程序中声明的 dll 中实现接口 - C++
- 如何在不使用qt Quick的情况下在qt桌面应用程序中实现qt虚拟键盘
- 仅使用 DLL *.h 头文件构建(compile.link)应用程序代码,并在运行时加载 DLL 实现(显式链接)
- 如何在具有 DLL 的应用程序中实现单一实例
- 在应用程序级别调整 TCP 数据包大小以实现最大吞吐量
- 实现 Web 应用程序的张量分解的最有效语言
- 如何在Qt中编写客户端-服务器应用程序并实现简单的协议
- 实现应用程序网络协议的安全问题
- 实现不会从全屏应用程序中窃取焦点的通知对话框?
- 如何实现类似电话簿的应用程序
- 为地铁应用程序实现 directx IMFmediaEngineProtectedContent 时遇到问题