Delphi 中的类型转换指针添加
Typecasting pointer addition in Delphi
我想了解如何在 Delphi 中进行类型转换,类似于 C/C++。
我要转换的 C++ 代码是这样的;
typedef struct tagEXT2_INODE
{
uint16_t i_mode; /* File mode */
uint16_t i_uid; /* Low 16 bits of Owner Uid */
uint32_t i_size; /* Size in bytes */
uint32_t i_atime; /* Access time */
uint32_t i_ctime; /* Creation time */
uint32_t i_mtime; /* Modification time */
uint32_t i_dtime; /* Deletion Time */
uint16_t i_gid; /* Low 16 bits of Group Id */
uint16_t i_links_count; /* Links count */
uint32_t i_blocks; /* Blocks count */
uint32_t i_flags; /* File flags */
union {
struct {
uint32_t l_i_reserved1;
} linux1;
struct {
uint32_t h_i_translator;
} hurd1;
struct {
uint32_t m_i_reserved1;
} masix1;
} osd1; /* OS dependent 1 */
uint32_t i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
uint32_t i_generation; /* File version (for NFS) */
uint32_t i_file_acl; /* File ACL */
// uint32_t i_dir_acl; /* Directory ACL */
uint32_t i_size_high; /* This is used store the high 32 bit of file size in large files */
uint32_t i_faddr; /* Fragment address */
union {
struct {
uint8_t l_i_frag; /* Fragment number */
uint8_t l_i_fsize; /* Fragment size */
uint16_t i_pad1;
uint16_t l_i_uid_high; /* these 2 fields */
uint16_t l_i_gid_high; /* were reserved2[0] */
uint32_t l_i_reserved2;
} linux2;
struct {
uint8_t h_i_frag; /* Fragment number */
uint8_t h_i_fsize; /* Fragment size */
uint16_t h_i_mode_high;
uint16_t h_i_uid_high;
uint16_t h_i_gid_high;
uint16_t h_i_author;
} hurd2;
struct {
uint8_t m_i_frag; /* Fragment number */
uint8_t m_i_fsize; /* Fragment size */
uint16_t m_pad1;
uint32_t m_i_reserved2[2];
} masix2;
} osd2; /* OS dependent 2 */
} __attribute__ ((__packed__)) EXT2_INODE;
EXT2_INODE *src;
char *inode_buffer;
int inode_index, ret = 0;
inode_buffer = (char *)malloc(4096);
src = (EXT2_INODE *)(inode_buffer + inode_index);
有人可以解释一下这个 src
是如何被转换成这样的吗?我将如何在 Delphi 中执行相同的操作?
谢谢
编辑:
这是我的 Ext2 iNode 记录;
输入
TExt2iNode = Record
i_mode : Word;
i_uid : Word;
i_size : Cardinal;
i_atime : Cardinal;
i_ctime : Cardinal;
i_mtime : Cardinal;
i_dtimes : Cardinal;
i_gid : Word;
i_links_count : Word;
i_blocks: Cardinal;
i_flags : Cardinal;
osd1 : Record
linux1 : Record
l_i_reserved1 : Cardinal;
end;
hurd1 : Record
h_i_translator: Cardinal;
End;
masix1 : Record
m_i_reserved1 : Cardinal;
End;
End;
i_block: array [0..EXT2_N_BLOCKS-1] of Cardinal;
i_generation : Cardinal;
i_file_acl : Cardinal;
i_size_high : Cardinal;
i_faddr : Cardinal;
osd2 : Record
Linux2 : Record
l_i_frag : Byte;
l_i_fsize : Byte;
i_pad1 : Word;
l_i_uid_high : Word;
l_i_gid_high : Word;
l_i_reserved2 : Cardinal
end;
hurd2 : Record
h_i_frag : Byte;
h_i_fsize : Byte;
h_i_mode_high : Word;
h_i_uid_high : Word;
h_i_gid_high : Word;
h_i_author : Word;
end;
masix2 : Record
m_i_frag:Byte;
m_i_fsize : Byte;
m_pad1 : Word;
m_i_reserved : array[0..1] of Cardinal;
end;
end;
End;
这是我的 Ex2 分区记录;
type
Ext2Partition = Class
private
handle: THandle;
sect_size: Integer;
total_sectors: Int64;
relative_sect: Int64;
linux_name :AnsiString;
inodes_per_group: integer;
inode_size: integer;
block_size: integer;
totalGRoups: Integer;
desc : TExt2_Group_Desc;
last_block : Cardinal;
inode_buffer : array of AnsiChar;
root : Ext2File;
buffercache : TList;
lvol : LogicalVolume;
public
onview, is_valid: boolean;
published
Constructor Create(size, offset :int64; ssise: integer; PHandle: THandle);
function read_inode(inum: Cardinal):Ext2File;
function readblock(blocknum: cardinal; var buffer: array of AnsiChar):integer;
function mount():integer;
End;
这是我的 read_inode
函数,指针计算在其中进行;
function Ext2Partition.read_inode(inum: Cardinal):Ext2File;
var
group, index, blknum: cardinal;
inode_index : integer;
ret: integer;
fFile: EXt2File;
src: TExt2iNode;
begin
if inum = 0 then
Result := NIL;
SetLength(self.inode_buffer, self.block_size);
group := (inum -1) DIV self.inodes_per_group;
if group > self.totalGRoups then
begin
//ShowMessage('Error reading iNode');
Result := -1;
end;
index := ((inum-1) MOD self.inodes_per_group) * self.inode_size;
inode_index := (index MOD self.block_size);
blknum := self.desc.bg_inode_table + (index div self.block_size);
if blknum <> self.last_block then
ret := readblock(blknum, self.inode_buffer);
fFile := TExt2iNode.Create;
//What goes here?
end;
代码分配了一块内存。在其他地方,它已经确定了该块内某处的 ext2 inode 结构的偏移量,由 inode_index
给出。它将偏移量添加到块的开头,给出结构的地址。然后代码对结果进行类型转换以告诉编译器计算出的 char*
地址实际上是该结构类型的地址。
使用直译,我们会有以下 Delphi 声明:
var
inode_buffer: PAnsiChar;
inode_index: Integer;
src: PExt2_Inode;
因此,要分配 src
,您需要完全按照 C++ 代码进行类型转换和添加:
src := PExt2_Inode(inode_buffer + inode_index);
大多数 Delphi指针类型默认不支持这种指针算法,但PAnsiChar
是特殊的。
到目前为止使用您的翻译,其中 inode_buffer
是一个数组而不是指向内存块的指针,您将改为:
src := PExt2_Inode(@inode_buffer[inode_index]);
索引数组,然后使用 @
运算符获取该数组元素的地址。 (实际上,如果 inode_buffer
也是我原来的 PAnsiChar
类型,您可以使用相同的语法。)
我想了解如何在 Delphi 中进行类型转换,类似于 C/C++。
我要转换的 C++ 代码是这样的;
typedef struct tagEXT2_INODE
{
uint16_t i_mode; /* File mode */
uint16_t i_uid; /* Low 16 bits of Owner Uid */
uint32_t i_size; /* Size in bytes */
uint32_t i_atime; /* Access time */
uint32_t i_ctime; /* Creation time */
uint32_t i_mtime; /* Modification time */
uint32_t i_dtime; /* Deletion Time */
uint16_t i_gid; /* Low 16 bits of Group Id */
uint16_t i_links_count; /* Links count */
uint32_t i_blocks; /* Blocks count */
uint32_t i_flags; /* File flags */
union {
struct {
uint32_t l_i_reserved1;
} linux1;
struct {
uint32_t h_i_translator;
} hurd1;
struct {
uint32_t m_i_reserved1;
} masix1;
} osd1; /* OS dependent 1 */
uint32_t i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
uint32_t i_generation; /* File version (for NFS) */
uint32_t i_file_acl; /* File ACL */
// uint32_t i_dir_acl; /* Directory ACL */
uint32_t i_size_high; /* This is used store the high 32 bit of file size in large files */
uint32_t i_faddr; /* Fragment address */
union {
struct {
uint8_t l_i_frag; /* Fragment number */
uint8_t l_i_fsize; /* Fragment size */
uint16_t i_pad1;
uint16_t l_i_uid_high; /* these 2 fields */
uint16_t l_i_gid_high; /* were reserved2[0] */
uint32_t l_i_reserved2;
} linux2;
struct {
uint8_t h_i_frag; /* Fragment number */
uint8_t h_i_fsize; /* Fragment size */
uint16_t h_i_mode_high;
uint16_t h_i_uid_high;
uint16_t h_i_gid_high;
uint16_t h_i_author;
} hurd2;
struct {
uint8_t m_i_frag; /* Fragment number */
uint8_t m_i_fsize; /* Fragment size */
uint16_t m_pad1;
uint32_t m_i_reserved2[2];
} masix2;
} osd2; /* OS dependent 2 */
} __attribute__ ((__packed__)) EXT2_INODE;
EXT2_INODE *src;
char *inode_buffer;
int inode_index, ret = 0;
inode_buffer = (char *)malloc(4096);
src = (EXT2_INODE *)(inode_buffer + inode_index);
有人可以解释一下这个 src
是如何被转换成这样的吗?我将如何在 Delphi 中执行相同的操作?
谢谢
编辑: 这是我的 Ext2 iNode 记录; 输入
TExt2iNode = Record
i_mode : Word;
i_uid : Word;
i_size : Cardinal;
i_atime : Cardinal;
i_ctime : Cardinal;
i_mtime : Cardinal;
i_dtimes : Cardinal;
i_gid : Word;
i_links_count : Word;
i_blocks: Cardinal;
i_flags : Cardinal;
osd1 : Record
linux1 : Record
l_i_reserved1 : Cardinal;
end;
hurd1 : Record
h_i_translator: Cardinal;
End;
masix1 : Record
m_i_reserved1 : Cardinal;
End;
End;
i_block: array [0..EXT2_N_BLOCKS-1] of Cardinal;
i_generation : Cardinal;
i_file_acl : Cardinal;
i_size_high : Cardinal;
i_faddr : Cardinal;
osd2 : Record
Linux2 : Record
l_i_frag : Byte;
l_i_fsize : Byte;
i_pad1 : Word;
l_i_uid_high : Word;
l_i_gid_high : Word;
l_i_reserved2 : Cardinal
end;
hurd2 : Record
h_i_frag : Byte;
h_i_fsize : Byte;
h_i_mode_high : Word;
h_i_uid_high : Word;
h_i_gid_high : Word;
h_i_author : Word;
end;
masix2 : Record
m_i_frag:Byte;
m_i_fsize : Byte;
m_pad1 : Word;
m_i_reserved : array[0..1] of Cardinal;
end;
end;
End;
这是我的 Ex2 分区记录;
type
Ext2Partition = Class
private
handle: THandle;
sect_size: Integer;
total_sectors: Int64;
relative_sect: Int64;
linux_name :AnsiString;
inodes_per_group: integer;
inode_size: integer;
block_size: integer;
totalGRoups: Integer;
desc : TExt2_Group_Desc;
last_block : Cardinal;
inode_buffer : array of AnsiChar;
root : Ext2File;
buffercache : TList;
lvol : LogicalVolume;
public
onview, is_valid: boolean;
published
Constructor Create(size, offset :int64; ssise: integer; PHandle: THandle);
function read_inode(inum: Cardinal):Ext2File;
function readblock(blocknum: cardinal; var buffer: array of AnsiChar):integer;
function mount():integer;
End;
这是我的 read_inode
函数,指针计算在其中进行;
function Ext2Partition.read_inode(inum: Cardinal):Ext2File;
var
group, index, blknum: cardinal;
inode_index : integer;
ret: integer;
fFile: EXt2File;
src: TExt2iNode;
begin
if inum = 0 then
Result := NIL;
SetLength(self.inode_buffer, self.block_size);
group := (inum -1) DIV self.inodes_per_group;
if group > self.totalGRoups then
begin
//ShowMessage('Error reading iNode');
Result := -1;
end;
index := ((inum-1) MOD self.inodes_per_group) * self.inode_size;
inode_index := (index MOD self.block_size);
blknum := self.desc.bg_inode_table + (index div self.block_size);
if blknum <> self.last_block then
ret := readblock(blknum, self.inode_buffer);
fFile := TExt2iNode.Create;
//What goes here?
end;
代码分配了一块内存。在其他地方,它已经确定了该块内某处的 ext2 inode 结构的偏移量,由 inode_index
给出。它将偏移量添加到块的开头,给出结构的地址。然后代码对结果进行类型转换以告诉编译器计算出的 char*
地址实际上是该结构类型的地址。
使用直译,我们会有以下 Delphi 声明:
var
inode_buffer: PAnsiChar;
inode_index: Integer;
src: PExt2_Inode;
因此,要分配 src
,您需要完全按照 C++ 代码进行类型转换和添加:
src := PExt2_Inode(inode_buffer + inode_index);
大多数 Delphi指针类型默认不支持这种指针算法,但PAnsiChar
是特殊的。
到目前为止使用您的翻译,其中 inode_buffer
是一个数组而不是指向内存块的指针,您将改为:
src := PExt2_Inode(@inode_buffer[inode_index]);
索引数组,然后使用 @
运算符获取该数组元素的地址。 (实际上,如果 inode_buffer
也是我原来的 PAnsiChar
类型,您可以使用相同的语法。)