【问题标题】:How to define "UCHAR * POINTER_32" and "VOID * POINTER_32" types in Delphi?Delphi中如何定义“UCHAR * POINTER_32”和“VOID * POINTER_32”类型?
【发布时间】:2013-06-13 09:49:34
【问题描述】:

背景:

为 64 位编译器翻译 IP_OPTION_INFORMATION32ICMP_ECHO_REPLY32 结构时,我遇到了要在那里使用的数据类型。参考资料中的结构定义:

IP_OPTION_INFORMATION32 结构:

typedef struct _IP_OPTION_INFORMATION32 {
  UCHAR              Ttl;
  UCHAR              Tos;
  UCHAR              Flags;
  UCHAR              OptionsSize;
  UCHAR * POINTER_32 OptionsData;
} IP_OPTION_INFORMATION32, *PIP_OPTION_INFORMATION32;

我会这样翻译(对于 Delphi XE2,64 位目标平台)。如您所见,我不知道该结构的OptionsData字段使用什么类型:

IP_OPTION_INFORMATION32 = record
  Ttl: UCHAR;
  Tos: UCHAR;
  Flags: UCHAR;
  OptionsSize: UCHAR;
  OptionsData:       // what should I use here for UCHAR * POINTER_32 ?
end;

ICMP_ECHO_REPLY32 结构:

typedef struct icmp_echo_reply32 {
  IPAddr                         Address;
  ULONG                          Status;
  ULONG                          RoundTripTime;
  USHORT                         DataSize;
  USHORT                         Reserved;
  VOID * POINTER_32              Data;
  struct ip_option_information32  Options;
} ICMP_ECHO_REPLY32, *PICMP_ECHO_REPLY32;

对于 Delphi XE2 64 位目标平台,我会写:

ICMP_ECHO_REPLY32 = record
  Address: TIPAddr;  // defined before
  Status: ULONG;
  RoundTripTime: ULONG;
  DataSize: USHORT;
  Reserved: USHORT;
  Data:              // what should I use here for VOID * POINTER_32 ?
  Options: IP_OPTION_INFORMATION32;
end;

问题:

您将如何在 Delphi 中为 64 位平台目标定义 UCHAR * POINTER_32VOID * POINTER_32 类型?据我所知,没有可用于 64 位平台目标的 32 位指针类型,我只是不喜欢定义它,例如作为Int32 类型:-)

上述类型的最精确翻译是什么?

【问题讨论】:

    标签: delphi winapi 64-bit delphi-xe2


    【解决方案1】:

    POINTER_32 的问题在另一个 Stack Overflow 问题中有所涉及:POINTER_32 - what is it, and why?

    当与在不同进程中定义的结构执行互操作时,您将使用它,该进程具有 32 位指针。

    您在 Delphi 中没有 __ptr32 的等价物,因此您别无选择,只能将其声明为 32 位整数。我会使用无符号类型。

    【讨论】:

    • 谢谢!我尝试在该字段中使用Cardinal,但要么我翻译了错误的结构,要么MS 的文档不正确。如果有人想玩,我的测试project is here。对于 64 位平台目标,对于 POINTER_32 数据类型,函数调用成功 only if I used Pointer。很奇怪……
    • 是的,我什至尝试将一些数据作为请求发送(RequestData 参数),但它是一样的。 IcmpSendEcho 函数调用只会失败并返回错误 87 (ERROR_INVALID_PARAMETER),除非我将 POINTER_32 数据类型定义为 Pointer,这与原始 POINTER_32 定义相反。
    • @TLama 我不知道你的程序有什么问题,但我的回答显然是准确的,正如这个简单的程序所证明的那样:pastebin.com/e7hGhtuf
    • 问题是我假设该字段是一个 32 位指针,但它实际上是一个指向 32 位指针的指针,不是吗?因此,尽管您的帖子是正确的,但我的问题的答案(如何在 Delphi 中为 64 位平台目标定义 UCHAR * POINTER_32VOID * POINTER_32 类型)实际上只是 Pointer 还是我错了?
    • 不,当您以 64 位为目标时,POINTER_32 宏的计算结果为 __ptr32。而UCHAR * __ptr32 是一个指向UCHAR 的32 位指针。
    【解决方案2】:

    在这种情况下,UInt32(或 Cardinal、DWORD 等 - 任何无符号 32 位)都可以。您需要做的就是在结构(记录)的适当位置声明无符号 32 位。 CPU 不会关心,编译器不会关心(如果需要,您可以将类型转换为指针)它实际上是否是指针。除非您对值和处理器的标志检查进行一些数学运算,否则即使有符号的 32 位也可以工作。 从 C 到 Delphi 的结构转换中的另一件事:确保原始对齐是 4 个字节(每个项目 32 位),因为 recordpacked record (无对齐)不同,默认情况下使用相同的 4 个字节对齐。否则,您可能会通过将记录应用于数据来遇到问题,例如

    type
      Picmp_echo_reply32 = ^icmp_echo_reply32;
    ...
      data_size := Picmp_echo_reply32(@mybuf[some_offset]).DataSize;
    

    var
      icmp_echo: Picmp_echo_reply32;
    ...
      icmp_echo := @buf[offset];
      reserved := icmp_echo.Reserved;
    

    【讨论】:

    • Delphi 的默认对齐方式与 Windows 头文件的默认对齐方式相匹配
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-01
    • 1970-01-01
    • 2021-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多