2

我遇到了以下 c 结构的问题:

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 显然计算了 76 的大小,并且它与 DLL 函数一起使用,但它让我有一些不好的感觉。有什么不对吗?有没有我现在没有想到的错误?

4

1 回答 1

0

您指定的显式布局与 [StructLayout] 的默认 Pack 值不兼容。默认值为 8,这需要在 Double 之前插入额外的 4 字节填充以保持对齐。pinvoke marshaller 通过仍然基于打包计算结构大小来解决这个问题。

通过明确指定包装来解决此问题:

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

显式设置 Size 属性也将修复它:

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

正确指定打包的更大优势是您现在不再需要显式指定偏移量。只有普通的 LayoutKind.Sequential 才能正常工作。

于 2012-04-14T15:52:31.160 回答