1

c# での c++ からの構造体の処理について質問があります。

次のようなサードパーティ製の C++ 構造体があります。

typedef struct 
{
//For application usage, will not access by the core
void* file;         //Application
void* lock;         //Application
void* appParam1;    //Application, maybe filename
unsigned int appParam2;     //Application, maybe length
void* appParam3;    //Application, maybe folder

//Will be used by the core and the hosting application
unsigned char streamMode;       //Read, Write or Append
unsigned int fileOffset;        //Actual file offset
unsigned char buf[DC_STREAM_BUF_SIZE];      //Buffer for reading and writing data
unsigned short bufSize;     //Buffer size, how much is filled from the buffer
unsigned short  bufOffset;      //Offset in reading and writing in the buffer
unsigned char queryData;        //Indicator if actual data are queried

//For internal use only, do not touch
unsigned char requestType;
signed int deviceId;
signed int param1;
unsigned short crc;
void* callback;
unsigned char objType;
void* obj;

} STREAM_HANDLE;

C# では、この構造体は次のように定義されます。

[StructLayoutAttribute(LayoutKind.Sequential), Serializable]
public class STREAM_HANDLE
{

    public IntPtr file;         
    public object lockobj;      
    public IntPtr appParam1;

    [MarshalAsAttribute(UnmanagedType.U4)] public uint appParam2;
    public IntPtr appParam3;

    [MarshalAsAttribute(UnmanagedType.U1)]public byte streamMode;

    [MarshalAsAttribute(UnmanagedType.U4)]public uint fileOffset;       

    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 0x0FFF)]public byte[] buf;

    [MarshalAsAttribute(UnmanagedType.U2)]public ushort bufSize;
    [MarshalAsAttribute(UnmanagedType.U2)]public ushort bufOffset;  
    [MarshalAsAttribute(UnmanagedType.U1)]public byte queryData;

    //For internal use only, do not touch
    [MarshalAsAttribute(UnmanagedType.U1)]public byte requestType;
    [MarshalAsAttribute(UnmanagedType.I4)]public int deviceId;
    [MarshalAsAttribute(UnmanagedType.I4)]public int param1;
    [MarshalAsAttribute(UnmanagedType.U2)]public ushort crc;

    public IntPtr callback;
    [MarshalAsAttribute(UnmanagedType.U1)]public byte objType;
    public IntPtr obj;
}

また、C# にはこの構造体への IntPtr があるため、このポインターを使用して C++ 関数を呼び出すことができます。これは非常にうまく機能します。

問題は、C++関数がそれを読み取れるように、C#から配列「buf」を埋めたいということです。これは動作しません。

これは、C# でハンドルを作成するために使用したコードです。

STREAM_HANDLE Handle = new STREAM_HANDLE
    {
        file = Marshal.StringToHGlobalAnsi(name),
        appParam1 = Marshal.StringToHGlobalAnsi(name),
        buf = new byte[0x0FFF],
        lockobj = new object(),
    };

 IntPtr HandlePointer = Marshal.AllocHGlobal(Marshal.SizeOf(Handle));
 Marshal.StructureToPtr(Handle, HandlePointer, true);

HandlePointer を使用していくつかの c++ 関数を呼び出す必要があり、c# の「buf」の内容を変更する必要があります。

4

1 に答える 1

0

属性は、フィールドが で割り当てられたときにインライン配列にマーシャリングされるMarshalAsことのみを保証します。その構造体の C# プレゼンテーションには、フィールドとして通常の .Net 配列参照があります。いつものように割り当てて初期化しました。必要に応じて使用する場合は、C# 表現とアンマネージ ハンドルを切り替える必要があります。bufMarshal.AllocHGlobal

fixed別の方法は、配列として宣言することです。これはunsafeコンテキストでのみ可能です:

unsafe struct InplaceArrayUnsafe
{
    public fixed byte Buf[10];
}

unsafe
{
    InplaceArrayUnsafe a;
    Console.WriteLine(a.Buf[4]);
    Debug.Assert(sizeof(a)); // can even do this
    UnmanagedFunction(&a); // and this
}
于 2013-01-15T10:31:37.600 に答える