このファイルを書き込んだ C++ アプリケーションは、Win32 x86 用にコンパイルされ、Win32 x86 上で実行されると仮定します。DataqFmt
これにより、配置された方法について推測することができます。これらの仮定が間違っている場合は、 や などの および関連する属性のさまざまなオプションを使用して調整できStructLayout
ます。MarshalAs
FieldOffset
まず、 と同じレイアウトの C# 構造体を使用しますDataqFmt
。
[StructLayout(LayoutKind.Sequential)]
struct DataqFmtCs
{
public ushort SR_number; // assuming the C++ type unsigned short is 2 bytes
public ushort SR_numerator;
public byte offset; // assuming the C++ type unsigned char was an unsigned and 1 byte
public byte nbytes;
public short hdr_bytes; // assuming the C++ type short was 2 bytes
public uint dat_bytes; // assuming the C++ type unsigned long was 4 bytes
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1144)]
public sbyte[] dummy; // assuming the C++ type char was signed and 1 byte
}
その構造では、生のバイトを取得するためにファイル I/O を実行する必要があります。
int dataqfmtSize = Marshal.SizeOf(typeof(DataqFmtCs));
var buffer = new byte[dataqfmtSize];
using (var fs = File.OpenRead("path\\to\\the\\file")) {
int bytesRead = fs.Read(buffer, 0, buffer.Length);
if (bytesRead != buffer.Length) {
// handle this
}
DataqFmtCs someThing = GetDataqFmtFromBuffer(buffer);
}
最後に、変換ルーチンがありGetDataqFmtFromBuffer
ます。
private static DataqFmtCs GetDataqFmtFromBuffer(byte[] buffer) {
GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
try {
return (DataFmtCs)Marshal.PtrToStructure(
handle.AddrOfPinnedObject(),
typeof(DataFmtCs));
} finally {
handle.Free();
}
}
Marshal.PtrToStrucutre
変換作業の大部分を行っています。コードの残りの部分は、構造体を定義し、基本的な .NET ファイル I/O を実行するだけです。
もう 1 つのオプション (エンディアン変換を実行する必要があることが多いため、プラットフォームに依存しない十分に文書化されたプロトコルを使用している場合、これは多くの場合良い解決策です) はStream
、BinaryReader
. これは演習として残しておきます。