C++ към Delphi - добавяне на структура и указател

Имам този макрос, дефиниран в 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 също е структура;

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;

Компилаторът обаче ми казва, че операторът не е приложим за този тип операнд.

Ето моята преобразувана c++ структура в записи на Delphi за ext4_extent_header и 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;

Благодаря!


person Jake Evans    schedule 11.02.2015    source източник
comment
Опитайте с Cardinal(hdr) + sizeof....   -  person 500 - Internal Server Error    schedule 11.02.2015
comment
Тъй като Pascal е силно въведен език, трябва изрично да конвертирате ptr в Cardinal тип (или в UIntPtr тип за повече удобство): Result := PExt4_ExtEnt(UIntPtr(hdr) + sizeof(ext4_extent_header));   -  person Abelisto    schedule 11.02.2015
comment
Също така трябва да използвате packed record вместо record, защото __packed__ директива в изходния C код.   -  person Abelisto    schedule 11.02.2015
comment
c или c++? Моля, използвайте съответния таг за езика и премахнете другия. C != C++.   -  person Tim Čas    schedule 11.02.2015


Отговори (2)


Предавайте hdr по същия начин, по който го прави C++ кодът. Той прехвърля указател към октет, така че аритметиката на указателя да третира отместването като октетна стойност. В Delphi:

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

Можете да активирате аритметиката на указателя и да я направите още по-проста:

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

Вероятно има друг проблем във вашия код. Ако hdr наистина беше PExt4_ExtEnt, тогава C++ нямаше да има нужда от макрос. Може просто да пише hdr + 1. Така че подозирам, че трябва да се задълбочите в C++ кода, за да разберете какво всъщност е hdr.


Обърнете внимание също, че C++ кодът указва, че тези записи са пакетирани. Използвайте packed record във вашия Delphi код за съответствие.

person David Heffernan    schedule 11.02.2015
comment
Не съм сигурен, че преобразува указател към някакъв по-сложен тип, тогава Cardinal е правилният начин само защото SizeOf връща размера в байтове, но увеличаването на указателя PType(p) го увеличава до размера на TType (просто опитайте да промените PAnsiChar на PWideChar във вашия пример и сравнете резултати). - person Abelisto; 11.02.2015
comment
Въпреки че вашето предложение сега даде възможност на моя код да се компилира, получавам различни резултати в Result в сравнение с C++ кода. Всъщност паметта в Result е напълно грешна. - person Jake Evans; 11.02.2015
comment
@Abelisto PAnsiChar традиционно е типът, който има налична аритметика на указателя. Това е доста добре познат идиом. Можете да използвате NativeUInt, ако предпочитате. PWideChar би било грешка. недей така Освен това изобщо не се превръщам в кардинал. - person David Heffernan; 11.02.2015
comment
@Jake Предполагам, че не си опаковал записите. - person David Heffernan; 11.02.2015
comment
@DavidHeffernan - Наистина опаковах записите, след като го предложихте в отговора си. - person Jake Evans; 11.02.2015
comment
Така че след това направете малко отстраняване на грешки. Извикайте макроса и функцията delphi, предавайки съответно NULL и nil. Отговорите трябва да са еднакви. Проверете съвпаденията на sizeof и за двата записа на двата езика. След като всичко се съгласи, вашият дефект е другаде. - person David Heffernan; 11.02.2015
comment
Вижте последната ми актуализация. Ако hdr е това, което твърдите, че е, макросът няма да е необходим. Така че мисля, че проблемите ви сега са другаде. - person David Heffernan; 11.02.2015
comment
Току-що актуализирах въпроса отново. hdr = ext4_extent_header - person Jake Evans; 11.02.2015
comment
Превъртях се назад. Моля, можем ли да се придържаме към зададения и отговорен въпрос. Моля, направете отстраняването на грешки, което описах. И накрая, нямам предвид типа hdr в паскал кода. Имам предвид в C++ кода. Ако наистина беше указател към заглавката на степента, нямаше да е необходим макрос. Все пак нека се концентрираме върху въпроса, моля. - person David Heffernan; 11.02.2015
comment
Оправих го. Ти беше права. Не предавах header като указател, а по-скоро като нерефериран указател. Благодаря. - person Jake Evans; 11.02.2015
comment
Истинският трик, когато се сблъскате с такъв проблем, е да го разделите на малки части. Продължавайте да доказвате, че всяка част работи. Докато правите това, вие стеснявате къде може да е повредата. - person David Heffernan; 11.02.2015

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) Къде ще сочи резултатът след това? Какво се намира непосредствено след hdr?

person Abelisto    schedule 11.02.2015