1

I have this macro defined in C++;

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

Where ext4_extent_header is a struct;

    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;

And ext4_extent is also a 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;

This is my attempt at writing it in Delphi;

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

However the compiler tells me that the Operator not applicable to this operand type.

Here is my converted c++ struct to Delphi record's for both ext4_extent_header and ext4_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;

Thanks!

4
  • 1
    Try with Cardinal(hdr) + sizeof.... Commented Feb 11, 2015 at 17:07
  • Since Pascal is a strong typed language you have to explicit convert ptr to Cardinal type (or to UIntPtr type for more convenience): Result := PExt4_ExtEnt(UIntPtr(hdr) + sizeof(ext4_extent_header)); Commented Feb 11, 2015 at 17:08
  • Also you have to use packed record instead of record because __packed__ directive in the source C code. Commented Feb 11, 2015 at 17:14
  • 1
    c or c++? Please use the appropriate tag for the language, and remove the other. C != C++. Commented Feb 11, 2015 at 17:19

2 Answers 2

1

Cast hdr the same way the C++ code does. It casts to pointer to octet so that the pointer arithmetic treats the offset as an octet value. In Delphi:

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

You could enable pointer arithmetic and make it even simpler:

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

There is probably another problem in your code. If hdr really was a PExt4_ExtEnt then the C++ would not need a macro. It could just write hdr + 1. So I suspect that you need to dig deeper into the C++ code to find out what hdr really is.


Note also that the C++ code specifies that these records are packed. Use packed record in your Delphi code to match.

Sign up to request clarification or add additional context in comments.

11 Comments

Not sure that is converting pointer to the some more complex type then Cardinal is a right way just because SizeOf returns size in bytes but increasing pointer PType(p) increases it to TType size (just try to change PAnsiChar to PWideChar in your example and compare results).
Whilst your suggestion now enabled my code to compile, I am getting different results in the Result compared to the C++ code. Actually the memory in the Result is completely wrong.
@Abelisto PAnsiChar is traditionally the type that has pointer arithmetic available. It's a reasonably well know idiom. You could use NativeUInt if you prefer. PWideChar would be a mistake. Don't do that. Also, I don't convert to cardinal at all.
I rolled back. Please can we stick to the question that was asked and answered. Please do the debugging that I described. Finally I don't mean the type of hdr in the pascal code. I mean in the C++ code. If it really was pointer to extent header no macro would be needed. All the same let's concentrate on the question please.
The real trick when facing such a problem is to break it down into small parts. Keep proving each part works. As you do so you narrow down where the fault can be.
|
1

1) Change your function to

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) Where Result will point after that? What is located immediately after hdr?

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.