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」の内容を変更する必要があります。