【问题标题】:C++ to Delphi - Struct and pointer additionC++ 到 Delphi - 结构和指针添加
【发布时间】:2015-02-11 16:53:56
【问题描述】:

我在 C++ 中定义了这个宏;

    #define EXT_FIRST_EXTENT(__hdr__) \
((struct ext4_extent *) (((char *) (__hdr__)) +         \
                         sizeof(struct ext4_extent_header)))

ext4_extent_header 是一个结构体;

    typedef struct ext4_extent_header {
    uint16_t  eh_magic;       /* probably will support different formats */
    uint16_t  eh_entries;     /* number of valid entries */
    uint16_t  eh_max;         /* capacity of store in entries */
    uint16_t  eh_depth;       /* has tree real underlying blocks? */
    uint32_t  eh_generation;  /* generation of the tree */
}__attribute__ ((__packed__)) EXT4_EXTENT_HEADER;

而ext4_extent也是一个struct;

typedef struct ext4_extent {
    uint32_t ee_block; /* first logical block extent covers */
    uint16_t ee_len; /* number of blocks covered by extent */
    uint16_t ee_start_hi; /* high 16 bits of physical block */
    uint32_t ee_start_lo; /* low 32 bits of physical block */
} __attribute__ ((__packed__)) EXT4_EXTENT;

这是我在 Delphi 中编写的尝试;

function Ext2Partition.EXT_First_Extent(hdr: PExt4_extent_header):PExt4_ExtEnt;
begin
  Result := PExt4_ExtEnt(hdr + sizeof(ext4_extent_header));
end;

但是编译器告诉我 Operator 不适用于此操作数类型。

这是我将 c++ 结构转换为 Delphi 记录的 ext4_extent_headerext4_extent

Type
  PExt4_extent_header = ^Ext4_extent_header;
  Ext4_extent_header = REcord
    eh_magic : Word;
    eh_entries : Word;
    eh_max : Word;
    eh_depth : Word;
    eh_generation : Cardinal;
  End;

Type
  PExt4_ExtEnt = ^Ext4_ExtEnt;
  Ext4_ExtEnt = Record
    ee_block : Cardinal;
    ee_len : Word;
    ee_start_hi : Word;
    ee_start_low : Cardinal;
  End;

谢谢!

【问题讨论】:

  • 试试Cardinal(hdr) + sizeof...
  • 由于 Pascal 是一种强类型语言,您必须将 ptr 显式转换为 Cardinal 类型(或转换为 UIntPtr 类型以更方便):Result := PExt4_ExtEnt(UIntPtr(hdr) + sizeof(ext4_extent_header));
  • 另外你必须使用packed record而不是record,因为源C代码中有__packed__指令。
  • cc++?请使用适当的语言标签,并删除其他标签。 C != C++。

标签: c++ delphi struct


【解决方案1】:

以与 C++ 代码相同的方式转换 hdr。它转换为指向八位字节的指针,以便指针算术将偏移量视为八位字节值。在德尔福:

Result := PExt4_ExtEnt(PAnsiChar(hdr) + sizeof(ext4_extent_header));

您可以启用指针运算并使其更简单:

{$POINTERMATH ON}
....
Result := hdr + 1;

您的代码中可能还有另一个问题。如果hdr 真的是PExt4_ExtEnt,那么C++ 就不需要宏了。它可以只写hdr + 1。所以我怀疑你需要更深入地研究 C++ 代码来找出hdr 的真正含义。


另请注意,C++ 代码指定这些记录是打包的。在您的 Delphi 代码中使用 packed record 进行匹配。

【讨论】:

  • 不确定将指针转换为更复杂的类型,然后 Cardinal 是正确的方法,因为 SizeOf 返回字节大小,但增加指针 PType(p) 会将其增加到 TType 大小(只需尝试在您的示例中将 PAnsiChar 更改为 PWideChar 并比较结果)。
  • 虽然您的建议现在使我的代码能够编译,但与 C++ 代码相比,我在 Result 中得到了不同的结果。其实Result中的内存是完全错误的。
  • @Abelisto PAnsiChar 传统上是具有可用指针算法的类型。这是一个相当广为人知的成语。如果您愿意,可以使用 NativeUInt。 PWideChar 将是一个错误。不要那样做。另外,我根本没有皈依红衣主教。
  • 我回滚了。请我们坚持提出并回答的问题。请进行我描述的调试。最后,我不是指帕斯卡代码中的 hdr 类型。我的意思是在 C++ 代码中。如果它真的是指向扩展头的指针,则不需要宏。还是让我们专注于这个问题吧。
  • 面对此类问题的真正诀窍是将其分解为小部分。继续证明每个部分都有效。当您这样做时,您可以缩小故障所在的范围。
【解决方案2】:

1) 将您的功能更改为

function Ext2Partition.EXT_First_Extent(hdr: PExt4_extent_header):PExt4_ExtEnt;
begin
  Inc(hdr, 1); // It will increase _local copy_ of the hdr parameter to size of Ext4_extent_header, not to 1 byte. Keep in mind such behavior 
  Result := hdr;
end;

2) 之后 Result 会指向哪里?紧跟在hdr 之后的是什么?

【讨论】:

    猜你喜欢
    • 2013-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-19
    • 1970-01-01
    • 1970-01-01
    • 2015-09-09
    • 1970-01-01
    相关资源
    最近更新 更多