C++ 如何在DLL和Windows二进制内存之间共享静态对象

C++ 如何在DLL和Windows二进制内存之间共享静态对象,c++,memory,memory-management,dll,C++,Memory,Memory Management,Dll,我有一个关于DLL的设计问题,我现在在维基百科中,问题如下: 我创建了一个系统,它有多个作为DLL实现的模块。它们在应用程序中使用,可以加载DLL,但并非所有DLL都是必需的。如果只做数学之类的事情,它就可以链接到“Utilities.dll”并使用它。 问题是,我有一个记录器/跟踪器。这会将所有内容记录到一个文件和一个调试控制台中,调试控制台只是一个流输出。问题是如何处理试图使用同一日志类的多个DLL。由于日志类位于这个“Utilities.dll”和类似“DataManagers.dll”的

我有一个关于DLL的设计问题,我现在在维基百科中,问题如下:

我创建了一个系统,它有多个作为DLL实现的模块。它们在应用程序中使用,可以加载DLL,但并非所有DLL都是必需的。如果只做数学之类的事情,它就可以链接到“Utilities.dll”并使用它。 问题是,我有一个记录器/跟踪器。这会将所有内容记录到一个文件和一个调试控制台中,调试控制台只是一个流输出。问题是如何处理试图使用同一日志类的多个DLL。由于日志类位于这个“Utilities.dll”和类似“DataManagers.dll”的东西以及其他dll中,所以它们也希望使用日志类功能。这包括登录到文件。我目前正在使用关键部分来确保不会发生写冲突,但如果关键部分是在usermode中实现的,那么我必须在某个时候切换到互斥体或类似的对象,才能拥有内核模式的对象。但如果在DLL内存中有多个log类实例,这意味着如果只使用一个关键部分,我将遇到一些严重的问题

我似乎无法拼凑的是,所有DLL都可以使用同一个日志类实例,而不必逐个链接到Utilities.DLL。我不想将8个dll加载到我的演示项目中,并让所有这些8个dll与日志类一起引用,如果我需要更多类似日志类的东西,这将有点连锁反应。有没有一种方法可以正确地做到这一点?使用类的功能,在其他DLL中的DLL中使用静态函数,在.exe windows二进制文件中使用相同的“静态”函数,从而不会在写入日志文件甚至调试控制台的输出流时发生冲突

如果我完全错了,试图做不可能的事,请告诉我,并帮助我尽可能接近这一点。我知道在DLL中使用单例模式时会出现类似的问题,但这可以通过

到目前为止,我所尝试的:

  • 初始化DLL的类时,给它们一个日志库的实例,但这会破坏类拥有所有静态成员的目的

我也发现了这个类似的问题(即使是我的全局工具所在的库的名称如何…),但它没有回答我的问题,并且有一点不同的方法,从09年开始

使用WinApi的CreatePipe或CreateNamedPipe函数,这是一个使用windows共享内存的类似队列的通信部分:

    BOOL WINAPI CreatePipe(
  __out         PHANDLE hReadPipe,
  __out         PHANDLE hWritePipe,
  __in          LPSECURITY_ATTRIBUTES lpPipeAttributes,
  __in          DWORD nSize
);

使用ReadFile和WriteFile通过管道与其他线程/进程进行通信

为了从管道中读取,进程在对ReadFile函数的调用中使用读取句柄。当以下情况之一为真时,ReadFile返回:在管道的写入端完成写入操作、已读取请求的字节数或发生错误

当进程使用WriteFile写入匿名管道时,只有在写入所有字节后,写入操作才会完成。如果管道缓冲区在写入所有字节之前已满,则WriteFile不会返回,直到另一个进程或线程使用ReadFile来提供更多的缓冲区空间

使用一个线程处理输入并将日志写入文件和/或控制台

关于管道的更多信息:

您的问题根本不是“DLL地狱”

这是一个基本了解DLL如何工作的问题。每个进程最多加载一次DLL。因此,如果您的DLL被多个其他DLL使用,那么它仍然会在每个进程中存在一次。如果日志类对象在DLL中实现为单个对象(例如全局对象),则每个进程有一个对象

然后,应保护一个对象,防止在进程内并发使用。关键部分是本地流程,与此完美匹配。您不需要互斥,因为两个进程各自都有自己的Utilities.DLL及其对象的副本


如果记录器登录到单个固定文件,则可能会出现问题。在这种情况下,两个进程将尝试登录到同一个文件。这是一个设计问题,你无论如何都不想去解决。将日志输出分开,确保每个记录器写入一个唯一的日志文件。

如下图所示

事实上,在一个进程中多次映射一个DLL是非常常见的(与一个非常流行的观点相反)!这是一个基本了解DLL如何工作的问题:-)


在干净的Windows XP系统上,您可以在iexplore.exe进程中看到dxtmsft.dll、ieframe.dll、iepeers.dll等的多个实例。所有这些Dll只是映射到不同的地址。

Dll。有什么问题吗?;)是的,一个DLL是很容易实现的,问题是当更多的人加入这个聚会时,一个管道如何解决他的问题呢?管道实际上只是一个文件,它需要另一个进程或至少另一个线程。仅仅引用微软的文档并不是一个真正的答案,尤其是当你没有明确说明你在引用的时候。管道不是一个文件!它是(正如我已经说过的)跨进程的可共享内存部分。它将以这样的方式解决问题,即可以像访问虚拟ram磁盘一样访问管道,进程/线程可以在其中进行写入或读取。您不需要显式地使用另一个进程来访问管道,但我建议使用一个工作线程来处理管道事务(读/写)。据我所知,他需要某种文件/控制台服务器,而不是使用同一类的数千个实例。问题更多的是,在一个进程中加载多个DLL将如何影响内存对象,如单例或静态类。我以前实现过WinAPI管道,但我更喜欢使用fstream来实现这个和块
    HANDLE WINAPI CreateNamedPipe(
  __in          LPCTSTR lpName,
  __in          DWORD dwOpenMode,
  __in          DWORD dwPipeMode,
  __in          DWORD nMaxInstances,
  __in          DWORD nOutBufferSize,
  __in          DWORD nInBufferSize,
  __in          DWORD nDefaultTimeOut,
  __in          LPSECURITY_ATTRIBUTES lpSecurityAttributes
);