(三)

 4    生成(Build )ARM  目的文件

 4.1      概述

     针对ARMI 的生成(Build)工作总体上比针对WINS 的要困难得多,因此,从一开始就寻找由gcc报告的额外编译错误和报警信息就是再正常不过了。首先这是由于: 在很多情况下gcc 比微软的编译器要严格得多,而且具有一些微妙的差异,它们在第一次的ARMI 生成(Build)过程中就会表现出来。下面几节涉及一些最通用的问题。

4.2      函数导出

     当定义导出函数时,gcc 的工具链比WINS工具链要严格得多。从某个DLL 导出一个函数的正确方式如下所示:

     在头文件中:

              class CMyClass : public CBase
              {
              IMPORT_C void Function();
              }

              在CPP 文件中:

              EXPORT_C void CMyClass::Function()
              {
              }

        WINS 工具链并不在意是否将EXPORT_C排除在CPP 文件之外了,总之它会导出该函数。然而,gcc工具链需要IMPORT_C和EXPORT_C 之间能完美匹配。如果不能,就不能从DLL 中导出该函数。最终,当试图连接这个DLL 时将导致如“无法找到函数”之类的错误。

4.3      来自PETRAN 的“MyDll.DLL has (un)initialized data”错误

       Symbian OS 架构并不允许DLLs 具有数据片(静态数据,已初始化的或未初始化的)。要确定这种数据片的意义是一个棘手问题: 
      *   该DLL 的所有用户都能共享它吗? 
      *   是否需要针对每个附着于该DLL 的处理都复制它? 
      *   在顶层存在着重要的运行时环境以解答任何可能的问题

     然而,由于WINS模拟器使用了底层Windows DLL 架构,它能用“copy-on-write”语法提供预处理DLL 数据。这就是为什么在为某台实际Symbian OS 设备生成(built )代码之前,总是查不出问题。

      请看本节中的C++代码,它被添加到了文件QSORT.CPP 中。该文件是ESTLIB.DLL的一部分。

              // variables
              struct div_t            uninitialised1;         // in .DATA
              static struct div_t  uninitialised2;// in .BSS
              struct div_t            initialised1 = {1,1};           // in .DATA
              static struct div_t  initialised2 = {2,2};// in .DATA

              // constants
              const struct div_t          const1 = {3,3};
              const static struct div_t  const2 = {4,4};
              const TPoint none(-1,-1);

static const TText* plpPduName[12] =
             {
             _S("Invalid"),
             _S("DataFlowOff"),
             _S("DataFlowOn"),
             _S("ConnectRequest"),
             _S("ConnectResponse"),
             _S("ChannelClose"),
             _S("Info"),
             _S("ChannelDisconnect"),
             _S("End"),
             _S("Delta"),
             _S("EndOfWrite"),
             _S("PartialWrite")
             };

             当生成这段代码时,来自PETRAN 的消息看上去如下所示:

             PETRAN - PE file preprocessor V01.00 (Build 170)

             WARNING: Dll 'ESTLIB[10003B0B].DLL' has initialised data.

             WARNING: Dll 'ESTLIB[100002C3].DLL' has uninitialised data.

             相关联的.map 文件含有能帮助向下追踪有关源文件的信息。

             请到Symbian OS/release/arm4/urel/dllname.map 查找。

             搜寻“.data”或“.data”。

             在这个范例中,我们发现:

             .data      0x10017000 0x200
                        0x10017000        __data_start__=.
              *(.data)
              .data     0x10017000 0x40 ../../Symbian
             OS/BUILD/STDLIB/BMMP/ESTLIB/ARM4/UREL/ESTLIB.in(QSORT.o)
                        0x10017000        initialised1
              *(.data2)
              *(SORT(.data$*))
                        0x10017040        __data_end__=.
              *(.data_cygwin_nocopy)
             .bss       0x10018000 0x18
                        0x10018000        __bss_start__=.
              *(.bss)
              .bss      0x10018000 0x18 ../../Symbian
             OS/BUILD/STDLIB/BMMP/ESTLIB/ARM4/UREL/ESTLIB.in(QSORT.o)
                        0x10018008        uninitialised1
              *(COMMON)
                        0x10018018        __bss_end__=.

     所以,该DLL 有0x18 字节的未初始化数据(.bss)和0x40 字节的已初始化数据(.data),所有这些都来自qsort.o。 initialised1和uninitialised1这两个变量都具有全局范围,所以.map文件按文件名列出了它们(并将两者都放进了已初始化数据中)。 从上面的代码中移去最前面四行,只留下被声明为const 的变量,但却只减少了.bss的0x08字节,及.data 的0x30字节。这里还存在两个问题:

如果C++对象有一个构造函数,那么将其定义为const也没什么用。虽然分配了未初始化数据的8个字节以保持Tpoint对象,但是在构造函数完成之前它并不会成为const。  const TText*声明表示,可能无法改变Ttext 的值,但它也不会使指针成为一个常量。已初始化数据的48个字节是plpPduName 阵列中的12个指针。要使这些指针成为常量,并使其指向的值 也成为常量,该声明中还需要在TText*后加上额外的const。

             static const TText* const plpPduName[12] =
             {
             _S("Invalid"),
             _S("DataFlowOff"),
             _S("DataFlowOn"),
             _S("ConnectRequest"),
             _S("ConnectResponse"),
             _S("ChannelClose"),
             _S("Info"),
             _S("ChannelDisconnect"),
             _S("End"),
             _S("Delta"),
             _S("EndOfWrite"), _S("PartialWrite")
             };

    移去Tpoint全局变量并向plpPduName 阵列添加额外的const,最终将导致移去最后出问题的
             .bss和.data。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值