如何使用运行时包构建“需要导入的数据引用”

时间:2012-05-09 08:33:15

标签: delphi delphi-xe2 runtime-packages resourcestring

为了帮助我们模块化单个应用程序,我们正在设置用于调试版本的包,同时仍然编译为单个exe版本。

我们的一个软件包(EAUtils)包含一个现在正在生成[DCC Error] E2201 Need imported data reference ($G) to access 'SMsgDlgWarning' from unit 'SystemUtils'的单元。

在构建EAUtils包本身时会发生这种情况。我还没有构建依赖于EAUtils的包。 EAUtils仅依赖于rtl / vcl包和我为Jedi WinApi单元创建的包。

这是行的结果:

// This is a TaskDialog override, with the same args as the old MessageDlg.
function TaskDialog(const aContent: string; const Icon: HICON = 0; 
  const Buttons: TTaskDialogCommonButtonFlags = TDCBF_OK_BUTTON): Integer;
const
  Captions: array[TMsgDlgType] of Pointer = (@SMsgDlgWarning, @SMsgDlgError, @SMsgDlgInformation, @SMsgDlgConfirm, nil);
var
  aMsgDlgType: TMsgDlgType;
  aTitle: string;
begin
  aMsgDlgType := TaskDialogIconToMsgDlgType(Icon);
  if aMsgDlgType <> mtCustom then
    aTitle := LoadResString(Captions[aMsgDlgType])
  else
    aTitle := Application.Title;

更具体地说,这是引用SMsgDlgWarningSMsgDlgErrorSMsgDlgInformationSMsgDlgConfirm的结果,这些都是Vcl.Const中声明的。

请注意,当我们构建单个可执行文件时,此代码会正确编译。

作为一种优化方法,我们的include文件确实包含{$IMPORTEDDATA OFF},因为这样可以更快地访问(全局)变量和常量。请参阅http://hallvards.blogspot.com/2006/09/hack13-access-globals-faster.html

根据有关错误的文档(http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/devcommon/cm_package_varref_xml.html),这就是原因并且它说“为了缓解这个问题,通常最简单的方法是打开$ IMPORTEDDATA开关并重新编译产生错误的单元。 “

所以,我在我们的包含文件中设置了{$IMPORTEDDATA ON},并通过在项目选项的Use imported data references部分中将Delphi Compiler | Compiling | Debugging设置为true来加倍确定。

不幸的是,与文档相反,这并没有缓解这个问题。即使将此编译器指令直接设置在违规代码之上并重建包也不会删除错误。

我还需要做些什么来解决这个E2201错误? 不确定,但SMsgDlgWarning及其朋友是资源字符串可能很重要吗?

1 个答案:

答案 0 :(得分:8)

错误消息是,恕我直言,误导,它是Vcl.Consts已用$G-编译而且导致了问题。 作为一种解决方法,您可以使用以下内容:

function Captions(AType: TMsgDlgType): Pointer;
begin
  Result := nil;

  case AType of
    TMsgDlgType.mtWarning:
      Result := @SMsgDlgWarning;
    TMsgDlgType.mtError:
      Result := @SMsgDlgError;
    TMsgDlgType.mtInformation:
      Result := @SMsgDlgInformation;
    TMsgDlgType.mtConfirmation:
      Result := @SMsgDlgConfirm;
  end;
end;

使用const数组的字符串编译(虽然它打破了本地化):

const
  Captions: array[TMsgDlgType] of string = (SMsgDlgWarning, SMsgDlgError, SMsgDlgInformation, SMsgDlgConfirm, '');

或者您可以使用{$G+}构建自己的包含Vcl。*单元的包,并使用它而不是标准vcl包。我更喜欢第一种解决方案;后者在部署后可能会产生更多问题(所谓的“DLL地狱”)。