2012-04-14 68 views
2

我遇到一個問題,下面的C結構:無效的結構尺寸時,編組C語言結構,以.NET

typedef struct tagTEXTUREPROP 
{ 
    DWORD dwSize; 
    DOUBLE eGloss; 
    DOUBLE eContrast; 
    BOOL bRepeat; 
    DOUBLE eDropX; 
    DOUBLE eDropY; 
    DOUBLE ePlacingPointX; 
    DOUBLE ePlacingPointY; 
    DOUBLE eWidth; 
    DOUBLE eHeight; 
    LONG nTransformation; 
} 
TEXTUREPROP; 

TYPE  C/C++   Description 
------------------------------------------------------------------- 
DWORD unsigned long Unsigned 32-bit integer. 
DOUBLE double   Double precision floating point (64-bit). 
BOOL  int    Signed 32-bit integer. 
LONG  long    Signed 32-bit integer. 

我從代碼理解上面什麼和定義是結構的大小必須是76字節。這是我目前使用的原始DLL函數期望作爲結構成員dwSize的值。任何其他值都會生成無效的結構大小錯誤消息。我正在生成一個.NET包裝,所以我不得不做一些編組。這裏是我的結構的翻譯:

<StructLayoutAttribute(LayoutKind.Explicit)> 
    Friend Structure TEXTUREPROP 
    <FieldOffset(0)> <MarshalAsAttribute(UnmanagedType.U4)> Public dwSize As UInteger 
    <FieldOffset(4)> <MarshalAsAttribute(UnmanagedType.R8)> Public eGloss As Double 
    <FieldOffset(12)> <MarshalAsAttribute(UnmanagedType.R8)> Public eContrast As Double 
    <FieldOffset(20)> <MarshalAsAttribute(UnmanagedType.I4)> Public bRepeat As Integer 
    <FieldOffset(24)> <MarshalAsAttribute(UnmanagedType.R8)> Public eDropX As Double 
    <FieldOffset(32)> <MarshalAsAttribute(UnmanagedType.R8)> Public eDropY As Double 
    <FieldOffset(40)> <MarshalAsAttribute(UnmanagedType.R8)> Public ePlacingPointX As Double 
    <FieldOffset(48)> <MarshalAsAttribute(UnmanagedType.R8)> Public ePlacingPointY As Double 
    <FieldOffset(56)> <MarshalAsAttribute(UnmanagedType.R8)> Public eWidth As Double 
    <FieldOffset(64)> <MarshalAsAttribute(UnmanagedType.R8)> Public eHeight As Double 
    <FieldOffset(72)> <MarshalAsAttribute(UnmanagedType.I4)> Public nTransformation As Integer 
    End Structure 

要計算結構的大小,我用下面的代碼:

Dim pFTP As New TEXTUREPROP With {.dwSize = Marshal.SizeOf(GetType(TEXTUREPROP))} 

但的dwSize所產生的價值,現在是80而不是76,這導致上述無效的結構尺寸錯誤。

When I change the structure to: 

<StructLayoutAttribute(LayoutKind.Explicit, Size:=76, CharSet:=CharSet.Ansi)> _ 
    Friend Structure FACE_TEXTUREPROP 
    [...] 
    End Structure 

的Marshal.SizeOf顯然計算大小爲76mm,並將其與DLL功能的工作原理,但它給我留下了一些不好的感覺。有什麼不對嗎?有沒有我現在沒有想到的錯誤?

回答

0

您指定的顯式佈局與[StructLayout]的默認Pack值不兼容。默認值是8,這要求在Double之前插入額外的4個字節的填充以保持對齊。通過編碼來彌補結構尺寸的不足。

修復此通過明確指定包裝:

<StructLayout(LayoutKind.Explicit, Pack:=4)> _ 
Friend Structure TEXTUREPROP 
    '' etc 
End Structure 

設置Size屬性明確將修復它太:

<StructLayout(LayoutKind.Explicit, Size:=76)> _ 
'' etc 

指定正確的包裝的更大的好處是,你現在不再需要明確指定偏移量。只是簡單的LayoutKind.Sequential將正常工作。

+0

你是對的。我唯一需要提及的是,當我使用刪除偏移量時,我必須再次製作LayoutKind.Sequential。 – Michael 2012-04-14 22:18:23

+0

好,好東西! – 2012-04-14 22:35:08