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の結果の値は76ではなく80になり、上記の無効な構造サイズエラーが発生します。

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]のデフォルトのパック値と互換性がありません。デフォルトは8で、Doubleの前に追加の4バイトのパディングを挿入して整列を維持する必要があります。pinvokeマーシャラーは、パッキングに基づいて構造サイズを計算することにより、これを少しフラブします。

パッキングを明示的に指定して、これを修正します。

<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 に答える