2013-02-25 128 views
1

如何在C#中用另一個結構的固定大小的數組聲明結構體?我需要this宣佈,以便它的工作。或者,如果我想創建bitmapinfo(-header),我的方法錯了嗎?另一個結構的固定大小數組的結構

[StructLayout(LayoutKind.Sequential)] 
public struct RGBQUAD 
{ 
    public byte b; 
    public byte g; 
    public byte r; 
    public byte reserved; 
} 

[StructLayout(LayoutKind.Sequential)] 
public struct BITMAPINFO 
{ 
    public BITMAPINFOHEADER bmiHeader; 
    [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.LPStruct, SizeConst = 1)] 
    public RGBQUAD[] bmiColors; 
} 

編輯:我得知自己是UnmanagedType.ByValArraySizeConst = 1在這裏很重要在44個字節的事件不斷保持BITMAPINFO元帥的大小,如果我給你256 RGBQUAD的大小的數組。

編輯2:但SizeConst一定不能小於實際的數組大小,否則非託管代碼可能會使應用程序崩潰。

+0

你不能聲明一個固定大小的結構體,你只能聲明一個結構體在interop期間如何被編組。 – 2013-02-25 16:38:18

+0

也許這會幫助嗎? http://www.pinvoke.net/default.aspx/Structures/BITMAPINFOHEADER。html – 2013-02-25 16:39:46

回答

3

正如註釋中所述,在C#中,您不能在結構中創建固定大小的結構數組。

但這不是你想要的。在申報

typedef struct tagBITMAPINFO { 
    BITMAPINFOHEADER bmiHeader; 
    RGBQUAD   bmiColors[1]; 
} BITMAPINFO, *PBITMAPINFO; 

bmiColors被聲明爲固定長度的陣列,但它確實對的RGBQUAD一個可變長度數組的佔位符。數組的實際長度取決於(in a slightly complicated way)的值bmiHeader.biClrUsed

如何在C#中處理這個問題完全取決於您對BITMAPINFO結構所做的操作。

更新

我剛剛看到您的其他問題。您將BITMAPINFO傳遞給SetDIBits,並且您的顏色表始終有256個條目。所以在聲明BITMAPINFO.bmiColors集合SizeConst設置爲256.

+0

我需要一個適用於任何調色板大小的可重用解決方案。所以我想保持原始大小爲1.這是否意味着我在這裏的聲明是正確的? – Bitterblue 2013-02-26 07:41:56

+0

將.Net中的結構編組爲本機API時,實際上會複製數據。如果將SizeConst設置爲1,則只有一個調色板條目會被複制。充其量,你的圖像顏色將是錯誤的。最糟糕的是,SetDIBits在讀取超過分配緩衝區的末尾時會崩潰。如果將其設置爲256,則不必使用所有條目。 – arx 2013-02-26 14:06:48

+0

是的,這至少在CreatePalette上修復了崩潰。如果我沒有256色但是16或8,我可以動態複製元帥嗎? – Bitterblue 2013-02-26 14:22:31

3

不幸的是(和恕我直言有點令人驚訝的是,.net的設計目標之一是促進與COM互操作).net運行時不理解任何種類的數組除了獨立的System.Array對象或內置到System.String中的字符數組。儘管C#提供了fixed數組類型,但是這些操作是使用指針算術以.net運行庫不能真正理解和無法驗證的方式進行的。

有可能創造一些通過定義與元件a0a1a2等一個結構和寫入,其使用switch語句或其它這樣的構建體,以它們的訪問元素的索引屬性的行爲類似於固定大小的數組,但這樣的結構可能比正常的數組執行速度慢得多。

如果您不需要使用safe代碼(並且考慮到您正在與可能不受信任的託管代碼進行互操作的事實,那麼「安全」代碼可能不是一個考慮因素)我建議您定義您的RGBQUAD使用顯式佈局,將int與其他數據重疊,然後讓其他結構包含fixed int[whateverSize];來保存RGB數據。其索引訪問器應該能夠通過讀取/寫入其「int」成員而相當有效地將int轉換爲RGBQUAD

相關問題