• dll 中使用ADO


    最近在把本人做的一个软件中的一些代码独立出来成为DLL模块供系统的其他组件调用。这些代码的最大特点是会在单元的Initialization中创建全局的静态对象,这些对象是数据库操作的封装,并在Finalization中释放。通过FastMM作为内存管理器并调整FastMM的参数,可以方便地直接使用Delphi的动态字符串进行参数传递。经过一轮鼓捣后,总结了一些问题如下:

    1、FastMM要打开ShareMem的相关几个选项,可以修改INC文件实现;

    2、需要向DLL传递Application.Handle,并在Dll中把接收到的值赋给DLL自己的Application.Handle。否则DLL中的窗体会接收不到键盘热键或者丢失某些消息;

    3、DLL中的窗体不能设置默认最大化,需要在创建窗体后WindowState := wsMaximized这样来最大化,否则最大化后的窗口位置不对;

    4、如果使用了ADO,由于ADO组件使用了COM接口,需要CoInitialize初始化。但是Delphi在COM的初始化中特意检查了当前程序是否DLL,如果是则跳过CoInitialize。很多人认为这个是Delphi的错误,但实际上这个是Microsoft的要求(可以在MSDN中查函数CoInitialize或CoUninitialize,有专门的说明)。就此来看,貌似只要在涉及到ADO的单元中加上CoInitialize和CoUninitialize便可。但是,由于Microsoft特意指出的,无法控制初始化/释放的顺序,结果会导致在Initialization中创建,在Finalization中释放的ADO对象在释放时可能由于已经CoUnitiialize而释放出错。解决办法只有:1)、所有ADO相关的对象都不能在Initialization/Finalization中处理;2)、使用动态加载的DLL 而不是静态加载,此时需要在主程序加载DLL前先执行CoInitialize。

    5、进一步的试验发现,静态加载并设置了共享MemoryManager的DLL会导致FastMM在退出时的内存泄露报告功能消失,原因不明。因此,所有用到FastMM的DLL都应该动态加载。

    最后贴一段我的DLL初始化代码:

    var
      OldDllProc: TDLLProc;

    procedure ThisDllProc(Reason: Integer);
    begin
      if Reason = DLL_THREAD_ATTACH then
        IsMultiThread := True; // for FastMM

      // for ADO
      case Reason of
        DLL_PROCESS_ATTACH,
        DLL_THREAD_ATTACH:CoInitialize(nil);

        DLL_PROCESS_DETACH,
        DLL_THREAD_DETACH:CoUninitialize;
      end;

      if Assigned(OldDllProc) then
        OldDllProc(Reason);
    end;

    begin
      OldDllProc := DllProc;
      DllProc := ThisDllProc;
      ThisDllProc(DLL_PROCESS_ATTACH);
    end.
  • 相关阅读:
    mybatis
    BeanUtil拷贝
    lombok(@Getter&@Setter)
    fly插件飞向购物车
    原生JavaScript判断是否为邮箱、危险字符、验证长度、验证网址、验证小数、整数、浮点数等常用的 js 验证
    原生JavaScript获取复选框的值
    原生JavaScript获取单选按钮的值
    原生JavaScript实现返回顶部的通用方法
    原生JavaScript获得URL中GET参数值
    原生JavaScript常用的正则表达式
  • 原文地址:https://www.cnblogs.com/moonwind/p/4444075.html
Copyright © 2020-2023  润新知