在 Delphi 中更改单元的初始化顺序

mpbci0fu  于 11个月前  发布在  其他
关注(0)|答案(3)|浏览(118)

我使用 Delphi XE7开发窗口32位应用程序。
我的应用程序包含许多单元,其中有一个初始化部分。我首先需要初始化一个特定的初始化部分。
可以设置优先级吗?我试着在dpr文件中写入初始化部分,但是编译器拒绝了。
请帮助我执行特定的初始化部分在第一次.提前感谢.

2eafrhcq

2eafrhcq1#

简单来说,初始化部分是按照uses子句中单元的引入顺序执行的。但是,由于单元的初始化只有在单元本身引用的任何单元初始化之后才执行 *(它们还没有初始化),因此它比这稍微复杂一点。
即:

program Foo;

  uses
    Unit1,
    Unit2,
    Unit3;

个字符
然后,装置初始化顺序为:

Unit3
Unit1
Unit2


这是因为Unit1引入了Unit3,所以即使Unit1dpr使用中列在第一位,Unit3实际上首先初始化,然后是Unit1的初始化。
如果你记得initialization部分出现在单元中任何uses子句之后,这是有意义的。
因此,绝对确保任何一个单元在 any other之前被初始化的唯一方法是将其首先列在DPRuses子句中,并且该单元不依赖于任何其他单元(除非这些单元不依赖于或干扰正在执行的初始化)。
当然,它不一定是 * 严格 * 第一。例如,如果您正在使用替换内存管理器,(例如FastMM),那么这绝对需要是你的dpruses子句中列出的第一个单元。你只需要确保你需要在任何其他单元之前初始化的单元。(你的单位)然后在任何其他单位之前列出,这可能会带来你的其他单位:

program  Foo;

uses
  FastMM,            // MUST be first but won't bring any of 'my' units in, so this is OK

  SysUtils,          // These too are fine coming next because again they don't
  Forms,             // reference 'my' units

  MyInitUnit,        // <- This is where it is important to list 'my' guaranteed first/earliest
                     //     initialisated unit of all 'my' units

  MyFirstAppUnit,    // And now the rest ...
  etc;


当然,如果你希望首先初始化的单元确实需要在 * 任何 * 其他单元之前初始化,包括RTL单元(与FastMM等需要的方式相同),那么你需要在dpruses列表中通过更早地声明你的单元来反映这一点。

x7yiwoj4

x7yiwoj42#

初始化部分按照单元在uses子句中出现的顺序执行。
因此,您可以通过在uses列表中向上移动单元来强制单元首先初始化。

cig3rfwq

cig3rfwq3#

不幸的是, Delphi 的文档是误导性的。从我自己的研究中,我发现单元并不总是按照它们在uses子句中引用的顺序初始化。如果你对我的发现不感兴趣,跳过下一段。
使用SysInternals的实用程序ProcMon并监视构建 Delphi 代码的过程,我可以看到单元文件何时打开,以及DCU文件何时写入。似乎单元文件是按照uses子句中引用它们的顺序打开的,但编译后的DCU可能会以不同的顺序写入。通过将断点放入初始化单元的部分我已经确认了它们是按照DCU写入磁盘的顺序调用的,而不是按照单元被引用的顺序。对于简单的情况,这两种顺序可以是等同的,但是,初始化代码总是按照unit子句中引用unit的顺序调用,这肯定是不正确的。

如何强制初始化订单

当单元需要以特定的顺序初始化时,我采用的方法是在每个需要初始化的单元中使用一个公共方法。该方法在initialization部分中被调用。
对于每个单元,都有一个单元级(私有)变量,用于指示初始化是否已运行。(对于简单的情况,布尔值就足够了,对于更复杂的情况,你可能会创建一个初始化对象,你可以使用一个指向它的指针)。然后在每个模块中,你检查你是否已经初始化,如果没有,你调用所有其他你需要在你之前初始化的单元的初始化,然后做你自己的初始化。
所以,在你使用简单布尔值的情况下,你可能有:

unit InitFirst;

interface

uses Classes;

procedure _DoInitialisation();

implementation

var
  _blInitialised: Boolean;

  procedure _DoInitialisation();
  begin
    if(not _blInitialised) then
    begin
      // initialisation code goes here
      _blInitialised:=True;
    end;
  end;

initialization

  _DoInitialisation();

end.

字符串

unit InitSecond;

interface

uses Classes;

procedure _DoInitialisation();

implementation

uses  InitFirst;

var
  _blInitialised: Boolean;

  procedure _DoInitialisation();
  begin
    if(not _blInitialised) then
    begin
      InitFirst._DoInitialisation();
      // initialisation code goes here
      _blInitialised:=True;
    end;
  end;

initialization

  _DoInitialisation();

end.

相关问题