代码之家  ›  专栏  ›  技术社区  ›  Crudler

Delphi动态dll-全局变量

  •  6
  • Crudler  · 技术社区  · 15 年前

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

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

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

    谢谢

    8 回复  |  直到 12 年前
        1
  •  4
  •   Tim Jarvis    15 年前

    我认为你有两个主要的选择。

    1. 提供您的函数的两个版本,一个是您现在拥有的版本,另一个是它们在缓冲区(记录,无论什么)中传递的版本,您可以从缓冲区中读取以前的状态,当然还可以将状态更新为。称之为函数的高性能版本。他们会想用的。

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

    选项1需要修改宿主应用程序,但这将迫使宿主应用程序开发人员利用,选项2不需要对宿主应用程序进行任何更改,但不会具有同样的性能。

    我个人并不想开始对引用计数进行胡乱的处理,假设主机应用程序正在卸载是有原因的,如果我是主机应用程序开发人员,那会让我很恼火。

        2
  •  4
  •   Daniel Rikowski    15 年前

    警告,肮脏的黑客:

    你可以自己装东西。

    每次召唤 LoadLibrary 增加参考计数器, FreeLibrary 减少它。只有当计数器达到零时,才会卸载DLL。

    因此,如果第一次加载DLL,您只需再次加载库,从而增加引用计数器。如果调用应用程序调用 自由主义者 引用计数器将递减,但不会卸载dll。

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

        3
  •  2
  •   skamradt    15 年前

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

    对于COM方法,除了请求(并保留)您将用于维护状态的COM对象的实例之外,服务不需要做太多的工作。因为它是一个单实例COM对象,所以所有请求都将指向同一个实例,从而允许您在请求之间保存状态。对对象的请求是序列化的,因此如果有多个客户端同时在同一台计算机上请求数据,这可能是性能问题。

        4
  •  1
  •   Toon Krijthe    15 年前

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

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

        5
  •  0
  •   zz1433    15 年前

    如果我是你,我会把这些全局变量的值保存到一个文件中,当文件被释放时,动态链接库将被加载,当它被初始化时。所以我没有理由在磁盘上保存dll的内存转储。

        6
  •  0
  •   A. I. Breveleri    15 年前

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

    - Al。

        7
  •  0
  •   Loren Pechtel    15 年前

    我同意先前关于全球国家信息具有危险性的评论,尽管我可以想象可能需要这样做。

    我提出了一个更清晰版本的Dr's Dirty Hack,它没有像Skamradt的答案那样永久的缺点:

    一个非常小的应用程序:

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

    任务1:加载DLL

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

    任务3:卸载DLL

    任务4:退出。

    安装程序:

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

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

        8
  •  0
  •   anuj arora Rob    12 年前

    这也可能有帮助

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

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