Delphi 2007-> 10.1 Berlin Port:解决E2251对StrLen的过度调用问题

时间:2016-05-12 02:19:13

标签: delphi delphi-2007 delphi-10.1-berlin

背景:将我的代码移植到Delphi 10.1 Berlin并通过第三方库。有些不再可用,所以我会尝试修复代码...

以下代码(将params从一个程序实例传递到另一个实例)引发了对StrLen的E2251 Ambiguious重载调用。我理解为什么,我只是不知道解决问题的最佳方法。

type
  PInstInfo = ^TInstInfo;
  TInstInfo = packed record
    FirstInstanceWnd:HWND;
    ParamCount:Integer;
    Params:Array[0..MAX_PARAMS-1, 0..MAX_PARAM_SIZE] of Char;
  end;

// Memory is filled with:
 lpInfo^.ParamCount:=ParamCount;
 if lpInfo^.ParamCount>MAX_PARAMS then
  lpInfo^.ParamCount:=MAX_PARAMS;
 for i:=0 to lpInfo^.ParamCount-1 do
 begin
  tempStr:=ParamStr(i+1);
  if length(tempStr)>MAX_PARAM_SIZE then
   setLength(tempStr,MAX_PARAM_SIZE);
  StrCopy(@(lpInfo^.Params[i,0]),PChar(tempStr));
 end;
 // and notify the first instance
 PostMessage(lpInfo^.FirstInstanceWnd, MSG_2ND_INSTANCE, 0, 0);



// And read using:
   if lpInfo <> nil then
   try
    // get Parameters
    params:=TStringList.Create;
    try
     for i:=0 to lpInfo^.ParamCount-1 do
     begin
      SetString(tempStr,
       PChar(@(lpInfo^.Params[i,0])),
       StrLen(@(lpInfo^.Params[i,0])));  <--- E2251 Ambiguious overloaded call to StrLen
      params.Add(tempStr);
     end;
     InstanceStarted(params);
    finally
     params.Free;
    end;

由于

1 个答案:

答案 0 :(得分:1)

默认情况下,@地址运算符会生成无类型指针。 StrLen()有两个重载版本,一个带PAnsiChar,另一个带PWideChar。可以将无类型指针传递给两个重载,从而产生歧义。 Delphi 2007中不存在PWideChar重载,这就是以前编译代码的原因。

要修复代码,您必须:

  1. 使用{$TYPEDADDRESS ON}{$T+}编译器指令启用Type-checked pointers,因此使用Char运算符获取@变量的地址将会产生一个类型化的PChar指针,而不是一个无类型的指针。

    {$TYPEDADDRESS ON}
    SetString(tempStr,
      @(lpInfo^.Params[i,0]),
      StrLen(@(lpInfo^.Params[i,0])));
    
  2. 使用您在SetString()的第二个参数中使用的相同类型转换:

    SetString(tempStr,
      PChar(@(lpInfo^.Params[i,0])),
      StrLen(PChar(@(lpInfo^.Params[i,0]))));
    
  3. 删除对SetString()StrLen()的调用,因为可以将以空值终止的字符指针直接分配给String变量:

    tempStr := PChar(@(lpInfo^.Params[i,0]));
    

    {$TYPEDADDRESS ON}
    tempStr := @(lpInfo^.Params[i,0]);
    
  4. 说到这一点,请注意在D2009中Char数据类型从Ansi更改为Unicode,因此此代码仅在将参数发送到应用程序的Unicode版本时才有效,而不是Ansi版本。如果您需要继续支持应用程序的旧版本,则应定义一个不同的窗口消息以传递Unicode参数,然后让您的Unicode应用程序支持两个用于接收的消息,并分析目标HWND以决定将哪个消息发送到用于发送。