6

我正忙于编写一个为主机应用程序提供多种功能的 dll。此应用程序动态调用 dll,在每次函数调用后加载和释放它。

我无法控制主机应用程序。我只能在 dll 中使用。有没有办法可以将某些变量保留在内存中,以便我可以在每个函数中重用它们?显然,当主机应用程序卸载 dll 时,全局变量会被清除。将 dll 保存到文件听起来很乱!

谁能建议一种分配我可以保持全局变量的方法?

谢谢

4

8 回答 8

4

警告,肮脏的黑客:

你可以自己加载。

每次调用LoadLibrary都会增加一个引用计数器,FreeLibrary减少它。只有当计数器达到零时,DLL 才会被卸载。

因此,如果您的 DLL 第一次被加载,您只需再次加载您的库,从而增加引用计数器。如果调用应用程序调用FreeLibrary引用计数器会递减,但 DLL 不会被卸载。

编辑:正如 mghi 指出的,如果进程终止,无论引用计数是否为零,DLL 都将被卸载。

于 2009-06-25T08:15:30.107 回答
4

我认为您在这里有两个主要选择。

  1. 提供 2 个版本的函数,一个是您现在拥有的,另一个是它们传入的缓冲区(记录等),您可以从中读取以前的状态,当然也可以将状态更新到其中。将此称为该函数的高性能版本。他们会想要使用它。

  2. 像在某个文件中保存 cookie(基本上就是这样)一样保存状态。

选项 1 需要对宿主应用程序进行修改,但对于宿主应用程序开发人员来说是有吸引力的,选项 2 不需要对宿主应用程序进行任何更改,但性能不高。

我个人不会倾向于开始讨论引用计数,大概主机应用程序正在卸载是有原因的,如果我是主机应用程序开发人员,那会惹恼我。

于 2009-06-25T09:30:41.033 回答
2

如果您要共享大量全局数据,另一种解决方案是创建一个 Windows 服务来“缓存”状态数据。您还需要实现某种跨进程边界工作的 IPC,例如内存映射文件、邮箱、COM(在这种情况下为单个实例)、TCP/IP 等。您可能会发现这种开销不仅仅是将状态写入文件,这就是为什么我只在状态数据量过多时才推荐这种方法,或者对于每个请求只处理整体的一部分进入你的dll。

对于 COM 方法,除了请求(并保持)您将用来维护状态的 com 对象的实例之外,服务不需要做太多事情。由于它是一个单实例 com 对象,所有请求都将发送到同一个实例,从而允许您在请求之间保存您的状态。对对象的请求是序列化的,因此如果您有多个客户端同时在同一台机器上请求数据,这可能是一个性能问题。

于 2009-06-25T16:08:28.123 回答
1

最好的方法是使用包含“全局变量”的类。您实例化一个对象并将其作为参数提供给 dll 函数。但这对您没有帮助,因为您无法更改呼叫应用程序。

如果必须将全局数据保存在 dll 中,解决方案是将它们写入文件。但这会对性能产生严重影响。

于 2009-06-25T08:10:11.337 回答
0

如果我是你,我会将这些全局变量的值保存到一个何时释放 dll 的文件中,并在初始化时加载它们。我没有理由将 dll 的内存转储保存在磁盘上。

于 2009-06-25T08:12:33.780 回答
0

释放 DLL 时将值写入注册表,并在加载 DLL 时从注册表中读取值。当读取发现未设置密钥时,不要忘记提供默认值。

-阿尔。

于 2009-06-25T19:09:22.483 回答
0

我同意之前关于全局状态信息危险的评论,尽管我可以想象它可能是必要的。

我提出了一个更干净的 DR 肮脏黑客版本,它没有像 skamradt 的回答那样永久存在的缺点:

一个非常小的应用程序:

它没有任何外观,它不会显示在任务栏上。

任务 #1:加载 DLL

任务 #2:使用它的命令行,运行它并等待它终止。

任务 #3:卸载 DLL

任务#4:退出。

安装程序:

它找到主应用程序的快捷方式并修改它们以便小应用程序运行,快捷方式指向的原始位置成为第一个参数。

结果: DLL 仅在主应用程序运行时保留在内存中,但不会在每次程序转储它时被卸载。

于 2009-06-25T19:23:02.583 回答
0

这也可能有帮助

option 1: 创建一个共享内存区域来保存由分页文件支持的变量 - 如果您能够打开该共享内存区域,则您的 dll 之前已加载(假设“私有”共享内存名称,可能命名为类似 process_id_yourdllname 的名称) - 如果可以'不要打开它,然后你第一次创建并初始化它。如果您创建它,那么您不必费心删除它 - 但如果您打开它,您会在卸载时关闭它。我相信当应用程序关闭时该区域将被释放,因为其他应用程序不应该拥有这个特定“私有”共享内存区域的句柄。

option 2: 创建仅用于管理全局变量的第二个 .dll。您的 dll A 可以加载该 dll B,而不是释放它,将您需要管理全局变量的任何内容放入 dll B。当应用程序消失时,它应该会消失,而且我认为您可能不需要关心所涉及的(可能是无用的)引用计数(因为您不会卸载 dll B)。

于 2009-10-01T12:49:33.947 回答