#pragma directive

#pragma package(smart_init)

#pragma package(smart_init)确保已打包的单元按照其依赖关系确定的顺序进行初始化(默认情况下包含在package(包)源文件中。)通常,您将#pragma package用于作为package(包)构建的.cpp文件。简而言之就是按照单元的依赖关系顺序进行初始化,一般用于构建Package(软件包)中

注意:不要在头文件中使用#pragma package(smart_init)。 这样做可能导致编译器错误。

该编译指令影响该编译单元的初始化顺序。 对于单元,初始化按以下顺序进行:

1)根据它们的“uses”依赖性,即,如果unitA依赖于unitB,则必须在unitA之前初始化unitB。

2)链接顺序。

3)单元(unit)内的优先级顺序。

 

对于常规目标文件(obj文件)(不是作为单元(unit)构建的目标文件),首先根据优先级顺序进行初始化,然后根据链接顺序进行初始化。 更改对象文件的链接顺序将更改全局对象构造函数的调用顺序。

以下示例显示了单元和常规目标文件之间的初始化有何不同。

假设您有三个源文件A,B和C,它们使用#pragma package(smart_init)“智能初始化”,并且具有优先级设置为10、20和30的函数(由#pragma startup的优先级参数定义)。这些函数是根据其优先级值和父源文件命名的,因此名称分别为a10,a20,a30,b10,b20等。这是三个程序A,B和C:

 

// A.cpp
#include <stdio.h>

#ifdef USE_PACKAGE_INIT
#pragma package(smart_init)
#endif

void A10() {
  printf("%s() ", __FUNCTION__);
}
#pragma startup A10 10

void A20() {
  printf("%s() ", __FUNCTION__);
}
#pragma startup A20 20

void A30() {
  printf("%s() ", __FUNCTION__);
}
#pragma startup A30 30

 

 

// B.cpp
#include <stdio.h>

#ifdef USE_PACKAGE_INIT
#pragma package(smart_init)
#endif

void B10() {
  printf("%s() ", __FUNCTION__);
}
#pragma startup B10 10

void B20() {
  printf("%s() ", __FUNCTION__);
}
#pragma startup B20 20

void B30() {
  printf("%s() ", __FUNCTION__);
}
#pragma startup B30 30

 

 

// C.cpp
#include <stdio.h>

#ifdef USE_PACKAGE_INIT
#pragma package(smart_init)
#endif

void C10() {
  printf("%s() ", __FUNCTION__);
}
#pragma startup C10 10

void C20() {
  printf("%s() ", __FUNCTION__);
}
#pragma startup C20 20

void C30() {
  printf("%s() ", __FUNCTION__);
}
#pragma startup C30 30

 

如果按编写的方式并定义了USE_PACKAGE_INIT来构建源文件,则会打印出以下内容:

> A10() A20() A30() B10() B20() B30() C10() C20() C30()

 

也就是说,优先级被忽略,每个单元一次运行其所有初始化。

如果您在未定义USE_PACKAGE_INIT的情况下构建源文件,则会得到完全不同的结果。 在这种情况下,运行程序时,将输出以下内容:

 

> A10() B10() C10() A20() B20() C20() A30() B30() C30()

 

也就是说,使用 startup优先级顺序。

由于这三个都是单元,并且如果A uses B和C,并且链接顺序是A,B,C,则初始化的顺序是:

> B10()B20()B30()C10()C20()C30() A10()A20()A30()

如果以上是目标文件,而不是单元,则顺序为:

> A10()B10()C10()A20()B20()C20()A30()B30()C30()

 

使用#pragma package(smart_init)的.cpp文件还要求从任意声明#pragma pragma(smart_init)的.cpp文件中到其他目标文件的任何#pragma link引用都必须由一个单元解析。仍然可以通过库解析对非对象文件的#pragma link引用,依此类推。

 

 

 

#pragma package(smart_init, weak)

#pragma package(smart_init,weak)指令会影响对象文件在包的.bpi和.bpl文件中的存储方式。 如果#pragma package(smart_init,weak)出现在单元文件中,则编译器将在可能的情况下从BPL中忽略该单元,并在另一个应用程序或程序包需要时创建该单元的未打包的本地副本。 使用此伪指令编译的单元被称为“弱包装”。

#pragma package(smart_init,weak)用于消除可能依赖于同一外部库的程序包之间的冲突。

包含#pragma package(smart_init,weak)指令的单元文件不得具有全局变量。

 

 

#pragma link

语法:

  

#pragma link "[path]modulename[.ext]"

#pragma link指令指示链接程序将指定文件链接到可执行文件中。

使用path参数指定目录。 缺省情况下,链接器在本地目录和链接器的-L选项指定的任何路径中搜索模块名称。

只要您使用默认文件类型,就不要指定modulename的文件扩展名(.ext)。 链接器为modulename的文件扩展名(.ext)假定以下默认值:

  • .obj extension for BCC32
  • .o extension for Clang-enhanced C++ compilers

因此,如果省略.ext,则会根据您当前的目标平台自动使用正确的扩展名。

posted @ 2020-09-06 09:20  MasterQi  阅读(282)  评论(0编辑  收藏  举报