2012-10-06 111 views
2

我正在使用Windows API並必須在Delphi record內重新創建a structure。我想我已經記下了,但是這個有點令人困惑,我需要確保我做對了。如何將RETRIEVAL_POINTERS_BUFFER結構轉換爲Delphi?

這裏的原有C++結構:

typedef struct RETRIEVAL_POINTERS_BUFFER { 
    DWORD   ExtentCount; 
    LARGE_INTEGER StartingVcn; 
    struct { 
    LARGE_INTEGER NextVcn; 
    LARGE_INTEGER Lcn; 
    } Extents[1]; 
} RETRIEVAL_POINTERS_BUFFER, *PRETRIEVAL_POINTERS_BUFFER; 

注意,有此結構內的陣列結構。這是我迷路的地方。如果我沒有記錯的話,德爾福版本應該是這樣的:

TExtent = record 
    NextVcn: Integer; 
    Lcn: Integer; 
    end; 

    TExtents = array of TExtent; 

    PRETRIEVAL_POINTERS_BUFFER = ^TRETRIEVAL_POINTERS_BUFFER; 
    TRETRIEVAL_POINTERS_BUFFER = record 
    ExtentCount: DWORD; 
    StartingVcn: Integer; 
    Extents: TExtents; 
    end; 

當我在Windows API中使用這樣的結構,它似乎工作。但是,由於結構內部有這個結構數組,所以我有點猶豫,我做了這個正確的。這看起來正確嗎?

+4

幾乎所有的東西都已經翻譯過了['JEDI'](http://www.koders.com/delphi/fid87C50F65617654141B73DFD6DAF36BC0B953BF75.aspx)。 – TLama

+0

@TLama,只要「幾乎」不是一個因素,我認爲這可能是我的答案。 –

+3

我的意思是幾乎所有的Windows API。你需要什麼[當然完成](http://www.koders.com/delphi/fid87C50F65617654141B73DFD6DAF36BC0B953BF75.aspx#L3913)。 – TLama

回答

6

Extents字段是內嵌在結構中的可變長度數組。實際的結構將有ExtentCount元素。你不能在這裏使用Delphi動態數組。事實上,你絕對不能在interop中使用Delphi動態數組。

因此,像C代碼那樣聲明它爲array [0..0]。爲了訪問它,你需要禁用範圍檢查。該記錄的實際實例將在索引0..ExtentCount-1中具有有效數據。

對於您的整體類型,在德爾福地圖DWORD在C到DWORD。並且在Delphi中使用LARGE_INTEGER的C到LARGE_INTEGER。這些都不是德爾福Integer相同。前者是無符號的,後者是64位寬。

PRetrievalPointersBuffer = ^TRetrievalPointersBuffer; 
TRetrievalPointersBuffer = record 
    ExtentCount: DWORD; 
    StartingVcn: LARGE_INTEGER; 
    Extents: array [0..0] of record 
    NextVcn: LARGE_INTEGER; 
    Lcn: LARGE_INTEGER; 
    end; 
end; 

LARGE_INTEGER類型是相當尷尬的工作。您可能更願意將這些字段聲明爲Int64


這種類型的結構是不變的堆分配。堆分配代碼必須計算出適合於可變長度數組中的ElementCount項所需的大小。如果您正在分配緩衝區,那麼您將需要單獨定義類型的內部記錄,以便您方便地將其命名爲SizeOf。如果API分配,那麼你就像上面那樣好。

+0

+1,尤其適合您的編輯。我幾乎總是給內部記錄一個單獨定義的類型。它使很多事情變得非常簡單。隨着記錄方法的引入,我會在'TRetrievalPointersBuffer'類型上添加一個方法,用於計算給定'ExtentCount'的總大小。 –

+1

@jeroen在這是我定義外部記錄內的內部類型。 –

+0

當您知道數組的上界時,您可以通過相應地聲明數組來使其位於堆棧中。不是這個特定的情況,但是假設你有'WCHAR Name [1]',並且你知道它至多有255個字符,那麼你可以將該字段定義爲'Name:WCHAR [0..254]'。 –

2

TExtents定義爲array of TExtent是一個錯誤。這是聲明它作爲一個動態數組,一個託管參考類型。你需要的是一個有界的數組,如array [x..y] of TExtent

這個C聲明很奇怪,但它聲明爲只有一個元素的數組。如果您想精確複製它,則應聲明它爲array [0..0] of TExtent

+0

它是一個可變長度數組。但是你不能這樣宣佈。實際的數組有ExtentCount元素。 –

2

StartingVcn,NextVcn和LCN被定義爲LARGE_INTEGER這是在WINNT.H定義如下:

typedef union _LARGE_INTEGER { 
    struct { 
     DWORD LowPart; 
     LONG HighPart; 
    } DUMMYSTRUCTNAME; 
    struct { 
     DWORD LowPart; 
     LONG HighPart; 
    } u; 
    LONGLONG QuadPart; 
} LARGE_INTEGER; 

根據您所使用的Delphi的版本,你所定義的結構可能無法正常工作。 LARGE_INTEGER應聲明如下:

LARGE_INTEGER = record 
    case Integer of 
    0: (LowPart: DWORD; 
     HighPart: Longint;); 
    1: (QuadPart: LONGLONG); 
end; 

LONGLONG實際上只是一個Int64。您可以使用LowPart和Highpart或QuadPart訪問此結構。

希望這會有所幫助。

+3

LARGE_INTEGER已經在Windows.pas中定義。 –