Delphi动态Dll-全局变量

Delphi动态Dll-全局变量,delphi,dll,global-variables,Delphi,Dll,Global Variables,我正忙于编写一个dll,它为主机应用程序提供了几个函数。 此应用程序动态调用dll,在每次函数调用后加载并释放它 我无法控制主机应用程序。我只能在dll中使用。 是否有一种方法可以将某些变量保存在内存中,以便在每个函数中重用它们?显然,当主机应用卸载dll时,会清除全局变量。 将dll保存到文件听起来非常混乱 有谁能建议一种方法来分配一个我可以保持全局的变量吗 谢谢最好的方法是使用包含“globals”的类。实例化对象并将其作为dll函数的参数。但这对您没有帮助,因为您无法更改呼叫应用程序 如果

我正忙于编写一个dll,它为主机应用程序提供了几个函数。 此应用程序动态调用dll,在每次函数调用后加载并释放它

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

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


谢谢

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


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

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

警告,恶意攻击:

你可以自己装

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

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


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

我认为这里有两个主要选项

  • 提供两个版本的函数,一个是您现在拥有的,另一个是它们在缓冲区(记录,任何东西)中传递的,您可以从中读取以前的状态,当然也可以将状态更新为。将其称为函数的高性能版本。他们会想要使用它

  • 将状态保存为文件中某个位置的cookie(基本上就是这样)

  • 选项1需要对主机应用程序进行修改,但会迫使主机应用程序开发人员利用,选项2不需要对主机应用程序进行任何更改,但性能不高


    我个人不想开始胡闹引用计数,可能主机应用程序正在卸载是有原因的,如果我是主机应用程序开发人员,这会让我很恼火。

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


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

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


    -Al.

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

    我建议对DR's dirty hack进行一个更干净的版本,它不会像skamradt的回答那样有永久性的缺点:

    非常小的应用程序:

    它没有任何外观,它阻止自己显示在任务栏上

    任务1:加载DLL

    任务2:获取它的命令行,运行它并等待它终止

    任务3:卸载DLL

    任务4:退出

    安装程序:

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


    结果:只有在主应用程序运行时,DLL才会保留在内存中,但不会在程序每次转储DLL时将其卸载。

    这也可能会有所帮助

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

    选项2:

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

    是的,但是这个方法在何时决定dll真正卸载自己上又添了很多麻烦,因为