delphi - 使用运行时包构建时如何解决 "Need imported data reference"

标签 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;

更具体地说,这是引用 SMsgDlgWarning 的结果, SMsgDlgError , SMsgDlgInformationSMsgDlgConfirm ,均在 Vcl.Const 中声明.

请注意,当我们构建单个可执行文件时,此代码编译不会出现错误。

作为一种优化手段,我们的包含文件确实包含 {$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项目选项部分。

不幸的是,与文档相反,这并没有缓解问题。即使直接在有问题的代码上方设置此编译器指令并重建包也无法消除错误。

我还需要做什么才能解决此 E2201 错误? 不确定,但 SMsgDlgWarning 及其 friend 是资源字符串可能很重要?

最佳答案

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

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 hell ”)。

关于delphi - 使用运行时包构建时如何解决 "Need imported data reference",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10512504/

相关文章:

delphi - GMLib 简单方向示例

德尔福XE2 : Application build with runtime package with FireMonkey framework

sql-server - 如何将 SQL BACKUP 命令的结果输出获取到 Delphi 程序中?

delphi - 是否可以将自己的帮助文件添加到 Delphi XE2 IDE 中?

wcf - Delphi:WSDL 文件中不包含 WSDL 对象

delphi - 如何销毁数组数组

delphi - 与运行时包链接

wpf - 为什么我的 WPF 应用程序中出现 "Unable to load DLL ' sqlite 3'"?

winforms - 如何在 WinForms 应用程序中使用 Delphi (2007) 控件?

delphi - 如何停止在 Delphi 10 Seattle IDE 中创建 .stat 文件