7

作为一般规则,我在使用指针时通过利用常量(无类型)参数而不是硬编码类型来规避许多经典设计陷阱。这给了我在执行高级图形功能时速度的好处,同时将技术细节留给编译器。它还使得在 Delphi 和 Free Pascal 中使用相同的代码变得很容易,只需进行最小的更改。然而,最近,由于 Embarcadero 对 Delphi 的演变及其即将推出的安全模型的模糊陈述,我开始质疑这一点。

例如,考虑以下示例:

Type TSomeDataProc = procedure (const aInput;var aOutput) of Object;

(* Convert 8-bit pixel to 16-bit pixel *)
Procedure TMyClass.ProcessSomeData08x565(Const aInput;var aOutput);
var r,g,b: Byte;
Begin
  FPalette.ExportTriplets(Byte(aInput),r,g,b);
  Word(aOutput):=(R SHR 3) SHL 11 or (G SHR 2) SHL 5 or (B SHR 3);
End;

(* Convert 16-bit pixel to 24-bit pixel *)
Procedure TMyClass.ProcessSomeData565x888(Const aInput;var aOutput);
Begin
  With TRGBTriple(aOutput) do
  Begin
   rgbtRed:=(((word(aInput) and $F800) shr 11) shl 3);
   rgbtGreen:= (((word(aInput) and $07E0) shr 5) shl 2);
   rgbtBlue:= ((word(aInput) and $001f) shl 3);
  end;
End;

我们现在有两个具有相同声明的过程,但它们处理像素数据的方式非常不同。这给了我们使用查找表来获得正确的“转换器”方法的好处。这应该在构造函数或分配图片位图的任何地方完成,如下所示:

Private
FLookup: Array[pf8bit..pf32bit,pf8bit..pf32bit] of TSomeDataProc;

Procedure TMyClass.Create;
Begin
  Inherited;
  FLookup[pf8bit,pf16bit]:=ProcessSomeData08x565;
  FLookup[pf16bit,pf24Bit]:=ProcessSomeData565x888;
end;

每当我们需要转换像素时,我们只需查找正确的方法并使用它。所有过程的语法保持不变——所以我们不必担心每个过程“如何”运行。就我们班而言,它们看起来都一样。

Procedure TMyClass.ConvertTo(aFormat:TpixelFormat);
Begin
 // Get function for the correct pixel converter
 FConvertProc:=FLookup[CurrentFormat,aFormat];

 //Use the pixel converter
 FConvertProc(GetSourcePixelAddr(x,y),GetTargetPixelAddr(x,y));
end;

问题是:这种类型转换(例如:Const to Byte 或任何已定义的 Record 类型)在 64 位下能否存活?我个人不明白为什么不这样做,但 Embarcadero 对新的“安全”模型和指针使用有点含糊,所以我发现在未来保护我的代码有点困难。

4

2 回答 2

3

由于在 RTL 中使用了这些技巧,因此我认为在没有大量代码破坏的情况下弃用 var 或 const 无类型参数。

Embarcadero 尽最大努力保持尽可能多的向后兼容性。

在首先发出有关使用外部汇编程序的一些通知之后,它们甚至应该在 64 位编译器中包含内联汇编。

而且这样的修改与 64 位模型没有任何关系,而 x86-64 汇编器是要编写的一段新代码。

所以你应该发布官方Embarcadero新闻组的这个问题,但我认为你不必担心这个。

于 2011-01-31T14:56:34.200 回答
1

请注意,FPC 已经更改了 CONST 参数,尽管在这种情况下没有。

对于正常情况,所有调用约定不再通过引用来保证 CONST,而是遵循相应 ABI 指定的任何内容。一个新的参数类型,CONSTREF 保证是通过引用。

像所有兼容性问题一样,问题在于 TP/Delphi CONST 始终是 ref,但 TP/Delphi 也始终是 x86。

除其他外,所有 STDCALL 函数都会更改,例如 IUnknown.Queryinterface:

http://wiki.freepascal.org/User_Changes_Trunk#IInterface.QueryInterface.2C_._AddRef_and_._Release_definitions_have_been_changed

原因或多或少是在这些情况下,x86 ABI 信息进入了通用接口,这不是跨架构兼容的。所以必须猜测它是语言的一部分,还是语言的 x86 实现的一部分。

请注意,IUnknown 也用于其他平台,例如 Firefox 的 XPCOM

Delphi 也可能会遇到这样的障碍,但我认为它们主要会影响具有显式调用约定要求的函数/方法,因为可以更改内部约定以满足需求,但实际上无法改变世界其他地方((XP) COM 或现有的 C(++) 库)以适应 Delphi 中的现有代码

于 2011-02-04T14:16:47.510 回答