这个程序
{$APPTYPE CONSOLE}
{$TYPEDADDRESS ON}
uses
Winapi.Windows;
procedure Foo(P: PDWORD);
begin
end;
procedure Bar;
var
dw: DWORD;
begin
Foo(@dw);
end;
begin
end.
在XE3中编译,但在XE4、XE5、XE6和XE7中不编译。误差在
Foo(@dw);
[dcc32 Error] E2010 Incompatible types: 'PDWORD' and 'Pointer'
感觉很奇怪。因此,经过一番挖掘,似乎问题归结为PDWORD
的定义。人们可能会自然而然地认为这将是:
PDWORD = ^DWORD;
事实上,XE3也是如此。在后来的版本中,我们发现:
// Note: Not ^DWORD yet
PDWORD = ^CppULongInt;
奇怪。那么,什么是CppULongInt
?
CppULongInt = type LongWord;
{$EXTERNALSYM CppULongInt 'unsigned long'}
{$OBJTYPENAME CppULongInt 'Bul' 'Gm'}
然后查看DWORD
的声明,我们发现:
//NOTE: DWORD should really be CppULongInt
DWORD = LongWord;
因此,CppULongInt
和DWORD
是不同的类型。这就是编译错误。
这是怎么回事CppULongInt
的作用是什么?为什么RTL设计者似乎想要将DWORD
别名为CppULongInt
。此更改是否与基于LLVM的x64 Windows C++编译器有关?我是世界上唯一一个使用{$TYPEDADDRESS ON}
的人吗?
注意,最后一个问题是反问句。
1条答案
按热度按时间wko9yo5t1#
(参考Why
PDWORD
is not a pointer toDWORD
。)看起来Embarcadero的某个人没有阅读相关的Windows文档:DWORD
被明确定义为 32 位unsigned integer
,因此在 Delphi 中它应该是UInt32
。PDWORD
被定义为指向DWORD
的指针,因此在 Delphi 中应该是PDWORD = ^DWORD
。DWORD_PTR
(不是PDWORD
!),后者的大小取决于 * 平台 *(32或64位),而不是unsigned long
的编译器定义。一个原因可能是他们试图在非Windows平台上使用
DWORD
和其他Windows数据类型,并试图保持它们的兼容性。如果是这样的话,在这种情况下,他们失败了,并引入了一个错误,因为使用的定义将无法在Windows中正常工作。