Delphi 中的指针类型转换

Pointer typecasting in Delphi

如何正确地类型转换为 Delphi 中的结构?这与 C++ 中的工作方式完全不同,根据 MSDN 文档,在 C++ 中只传递 &Data

program Project1;

uses
  System.SysUtils,
  Winapi.Windows,
  Winapi.Winsock2;

function WSAStartup(wVersionRequired: WORD; out lpWSAData: LPWSADATA): Integer; WINAPI; external 'ws2_32.dll';

var
  Data: WSADATA;
begin
  WSAStartup(WINSOCK_VERSION, LPWSADATA(@Data)); // E2197 Constant object cannot be passed as var parameter
  ReadLn;
end.

我想您已经翻译了 MSDN 文档中的函数,该文档如下:

int WSAStartup(
  _In_  WORD      wVersionRequested,
  _Out_ LPWSADATA lpWSAData
);

混淆源于使用 _Out_ 注释。那是一个扩展为无的宏。它用于向工具传达意图,例如,将头文件声明转换为不同的语言。可以在此处找到更多信息:

  • What is the meaning of _In_ and _Out_ in documentation of any function?
  • What is the purpose of __in __out __in_opt __allowed(), how do they work? Should I use similar constructs in my own code?

您错误地将 _Out_ 翻译成了 Delphi out 关键字。您可以简单地删除该关键字,您的声明将是正确的:

function WSAStartup(wVersionRequired: WORD; lpWSAData: LPWSADATA): Integer; 
  WINAPI; external 'ws2_32.dll';

那么您的电话将是:

WSAStartup(WINSOCK_VERSION, @Data);

或者,由于此参数不是可选的,您可以这样翻译它:

function WSAStartup(wVersionRequired: WORD; out lpWSAData: WSADATA): Integer; 
  WINAPI; external 'ws2_32.dll';

然后你会这样调用:

WSAStartup(WINSOCK_VERSION, Data);

但是,您应该使用可以在 Winapi.Winsock2 中找到的函数声明,从而避免犯此类错误的风险。也就是说,假设 Embarcadero 没有在翻译中犯错误,这种情况有时会发生。

最后,如果我不责备您(至少是温和地)忽略函数调用的 return 值,那将是我的失职。