#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,则会根据您当前的目标平台自动使用正确的扩展名。

#pragma directive的更多相关文章

  1. #pragma Directive in C/C++

    The #pragma is complier specified. for example, the code below does not work in gcc. #pragma startup ...

  2. 重新梳理HTML基础知识

    缘起 HTML(HyperText Markup Language超文本标记语言)是用于构建web页面的标记语言和通用标准.它并不是一项新的发明,因为超文本(具有超链接的文本)和标记语言(用于电子文档 ...

  3. C中的预编译宏定义

     可以用宏判断是否为ARC环境 #if _has_feature(objc_arc) #else //MRC #endif C中的预编译宏定义 -- 作者: infobillows 来源:网络 在将一 ...

  4. How do I place a group of functions or variables in a specific section?

    http://supp.iar.com/Support/?Note=27498 EWARM v5.xx (and newer) The placement of a few functions in ...

  5. RFC 2616

    Network Working Group R. Fielding Request for Comments: 2616 UC Irvine Obsoletes: 2068 J. Gettys Cat ...

  6. 基于NodeJs的网页爬虫的构建(一)

    好久没写博客了,这段时间已经忙成狗,半年时间就这么没了,必须得做一下总结否则白忙.接下去可能会有一系列的总结,都是关于定向爬虫(干了好几个月后才知道这个名词)的构建方法,实现平台是Node.JS. 背 ...

  7. scanf()常犯错误

    ------------------------------------------------------------------------ <> 本意:接收字符串. 写成代码:voi ...

  8. RFC2616-HTTP1.1-Header Field Definitions(头字段规定部分—单词注释版)

    part of Hypertext Transfer Protocol -- HTTP/1.1RFC 2616 Fielding, et al. 14 Header Field Definitions ...

  9. HTML5 Differences from HTML4

    Abstract "HTML5 Differences from HTML4" describes the differences of the HTML5 specificati ...

  10. C预编译, 预处理, C/C++头文件, 编译控制,

    在所有的预处理指令中,#Pragma 指令可能是最复杂的了,它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作.#pragma指令对每个编译器给出了一个方法,在保持与C和C++语言完全兼容的 ...

随机推荐

  1. JSP第五次作业

    1.教材P78-79  例4-9 1 <%@ page language="java" import="java.util.*" pageEncoding ...

  2. Python装饰器实例讲解(一)

    Python装饰器实例讲解(一) 多种角度讲述这个知识,这是个系列文章 但前后未必有一定的顺承关系 部分参考网络 本文以一个小案例引出装饰器的一些特点,不涉及理论,后面再谈 案例 写一个代码来求一个数 ...

  3. Spring boot 3.0 日志

    spring boot 3.0 已经自己集成了日志功能  logback SpringBoot 启动时自动加载配置文件,配置文件的默认名称为: logback.xml 或 logback-test.x ...

  4. Vue15 v-for和key的作用及原理

    部分转自https://blog.csdn.net/cun_king/article/details/120714227 1 v-for指令 1.1 简介 用于遍历. 当在组件中使用 v-for 时, ...

  5. GIT安装及IDEA配置(GIT)

    参考:https://blog.csdn.net/qq_40563761/article/details/91347443 1.安装git 2.idea下载GITHUB/GITEE插件 3.idea配 ...

  6. [java安全基础 01]SQL+反序列化

    tomcat Servlet 什么是servlet Java Servlet是运行在 Web 服务器或应用服务器上的程序.它是作为来自Web浏览器或其他HTTP客户端的请求和HTTP服务器上的数据库或 ...

  7. C# 数字转大写汉字

    1.数字转换成汉字大写public string NumToChinese(string x) { //数字转换为中文后的数组 string[] P_array_num = new string[] ...

  8. 学习笔记3:Android Studio 配置NDK编译c++代码

    NDK编译c++代码有两个方式: 1  ndk-build.cmd + Android.mk + Application.mk 编译, 可单独用ndk编译, 不使用IDE,使用Android需要配置b ...

  9. VMware-包体选择

    3.二进制包如何选择3.1选择适合当前系统的版本号:    ●找不到适合的,才去尝试别的系统版本号   ●el6兼容el5; el5无法安装el63.2选择适合cpu的架构:   ●x86_ _64包 ...

  10. openssl用法详解 【转】

    原文: http://www.178linux.com/48764 OpenSSL 是一个开源项目,其组成主要包括一下三个组件: openssl:多用途的命令行工具 libcrypto:加密算法库 l ...