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

Mar*_*ema 5 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;
Run Code Online (Sandbox Code Playgroud)

更具体地讲这是引用一个结果SMsgDlgWarning,SMsgDlgError,SMsgDlgInformationSMsgDlgConfirm,这都是声明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 referencesDelphi Compiler | Compiling | Debugging部分中设置为true来加倍确定.

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

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

Ond*_*lle 9

错误消息是,恕我直言,误导,它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;
Run Code Online (Sandbox Code Playgroud)

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

const
  Captions: array[TMsgDlgType] of string = (SMsgDlgWarning, SMsgDlgError, SMsgDlgInformation, SMsgDlgConfirm, '');
Run Code Online (Sandbox Code Playgroud)

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