Delphi 2007->10.1 柏林港:解决 E2251 对 StrLen 的模糊过载调用
Delphi 2007->10.1 Berlin Port: Solving E2251 Ambiguious overloaded call to StrLen
背景:将我的代码移植到 Delphi 10.1 Berlin 并使用第三方库。有些不再可用,所以我会尝试修复代码...
以下代码(将参数从一个程序实例传递到另一个程序实例)引发了 E2251 对 StrLen 的不明确过载调用。我明白为什么,我只是不知道最好的解决方法。
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;
谢谢
默认情况下,@
地址运算符生成一个无类型指针。 StrLen()
有两个重载版本,一个使用 PAnsiChar
,一个使用 PWideChar
。无类型指针可以传递给两个重载,因此会产生歧义。 PWideChar
重载在 Delphi 2007 中不存在,这就是之前编译代码的原因。
要修复代码,您必须:
使用 {$TYPEDADDRESS ON}
或 {$T+}
编译器指令启用 Type-checked pointers 因此使用 [=14= 获取 Char
变量的地址] 运算符将生成类型化 PChar
指针而不是非类型化指针。
{$TYPEDADDRESS ON}
SetString(tempStr,
@(lpInfo^.Params[i,0]),
StrLen(@(lpInfo^.Params[i,0])));
使用与 SetString()
的第二个参数相同的类型转换:
SetString(tempStr,
PChar(@(lpInfo^.Params[i,0])),
StrLen(PChar(@(lpInfo^.Params[i,0]))));
摆脱对 SetString()
和 StrLen()
的调用,因为可以将空终止字符指针直接分配给 String
变量:
tempStr := PChar(@(lpInfo^.Params[i,0]));
{$TYPEDADDRESS ON}
tempStr := @(lpInfo^.Params[i,0]);
尽管如此,请注意 Char
数据类型在 D2009 中从 Ansi 更改为 Unicode,因此此代码仅在将参数发送到应用程序的 Unicode 版本时有效,而不是 Ansi 版本.如果您需要继续支持您的应用程序的旧版本,您应该定义一个不同的 window 消息来传递 Unicode 参数,然后让您的 Unicode 应用程序支持两种消息的接收,并分析目标 HWND
以决定使用哪条消息发送。
背景:将我的代码移植到 Delphi 10.1 Berlin 并使用第三方库。有些不再可用,所以我会尝试修复代码...
以下代码(将参数从一个程序实例传递到另一个程序实例)引发了 E2251 对 StrLen 的不明确过载调用。我明白为什么,我只是不知道最好的解决方法。
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;
谢谢
默认情况下,@
地址运算符生成一个无类型指针。 StrLen()
有两个重载版本,一个使用 PAnsiChar
,一个使用 PWideChar
。无类型指针可以传递给两个重载,因此会产生歧义。 PWideChar
重载在 Delphi 2007 中不存在,这就是之前编译代码的原因。
要修复代码,您必须:
使用
{$TYPEDADDRESS ON}
或{$T+}
编译器指令启用 Type-checked pointers 因此使用 [=14= 获取Char
变量的地址] 运算符将生成类型化PChar
指针而不是非类型化指针。{$TYPEDADDRESS ON} SetString(tempStr, @(lpInfo^.Params[i,0]), StrLen(@(lpInfo^.Params[i,0])));
使用与
SetString()
的第二个参数相同的类型转换:SetString(tempStr, PChar(@(lpInfo^.Params[i,0])), StrLen(PChar(@(lpInfo^.Params[i,0]))));
摆脱对
SetString()
和StrLen()
的调用,因为可以将空终止字符指针直接分配给String
变量:tempStr := PChar(@(lpInfo^.Params[i,0]));
{$TYPEDADDRESS ON} tempStr := @(lpInfo^.Params[i,0]);
尽管如此,请注意 Char
数据类型在 D2009 中从 Ansi 更改为 Unicode,因此此代码仅在将参数发送到应用程序的 Unicode 版本时有效,而不是 Ansi 版本.如果您需要继续支持您的应用程序的旧版本,您应该定义一个不同的 window 消息来传递 Unicode 参数,然后让您的 Unicode 应用程序支持两种消息的接收,并分析目标 HWND
以决定使用哪条消息发送。