C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[4]: C++で書き出された構造体をC#で読み込む


(過去ログ 125 を表示中)

[トピック内 7 記事 (1 - 7 表示)]  << 0 >>

■74506 / inTopicNo.1)  C++で書き出された構造体をC#で読み込む
  
□投稿者/ nobb (70回)-(2015/01/07(Wed) 17:50:54)

分類:[C#] 

C++(MFC)で書き出されたファイルにある構造体をC#側で読み込みたいと思い、
自分なりにやってみたところ、読み込みは出来るのですが8バイト程ずれて読み込んでしまっているようです。
恐らくC#側の構造体のうちどこかのデータ型が間違っていると思うのですが、見つけられません。

どこがおかしいか教えてください。

目的:C++で書き出された複数のEstimate構造体があるファイルを読み込みC#で利用する
現状:読み込み自体はできているが、8バイトずれて読み込まれてしまう。
環境:Visual Studio 2013 Update4
言語:C#、.NET Framework4.5

== C++側構造体定義 ==
struct Tails
{
  int price;
  int netprice;
  int cost;
  int costratio;
  short ratio;
  int k_tan;
  int mbase;
  int attr1;
  int attr2;
  int add;
  int uke;
  int ukekin;
};


struct Estimate
{
  short dataflag;
  short datacode;
  short contents;
  short line;
  short bnumber;
  short mstflag;
  char name[30];
  char shape[30];
  char unit[6];
  int number;
  int tanka;
  double kingaku;
  char biko[16];
  Tails Ztail;
  Tails Rtail;
};


== C#側構造体定義 ==
[StructLayout(LayoutKind.Sequential)]
public struct Tails
{
  public int price;
  public int netprice;
  public int cost;
  public int costratio;
  public short ratio;
  public int k_tan;
  public int mbase;
  public int attr1;
  public int attr2;
  public int add;
  public int uke;
  public int ukekin;
}

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public struct Estimate
{
  public short dataflag;
  public short datacode;
  public short contents;
  public short line;
  public short bnumber;
  public short mstflag;
  [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 30)]
  public string name;
  [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 30)]
  public string shape;
  [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 6)]
  public string unit;
  public int number;
  public int tanka;
  public double kingaku;
  [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
  public string biko;
  public Tails Ztail;
  public Tails Rtail;
}

== C#側読み込みの実装 ==
private void btn1_Click(object sender, RoutedEventArgs e)
{
  using (FileStream fs = new FileStream(@"C:\Hoge\fuga.dat", FileMode.Open))
  using (BinaryReader reader = new BinaryReader(fs))
  {
    int readCount = Marshal.SizeOf(typeof(Estimate));
    //var buf = reader.ReadBytes(readCount);
    byte[] buf = null;
    do
    {
      buf = reader.ReadBytes(readCount);
      var handle = GCHandle.Alloc(buf, GCHandleType.Pinned);

      try
      {
        var obj = Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(Estimate));
      }
      finally
      {
        handle.Free();
      }
    } while (buf.Length == readCount);

  }
}

引用返信 編集キー/
■74508 / inTopicNo.2)  Re[1]: C++で書き出された構造体をC#で読み込む
□投稿者/ PANG2 (52回)-(2015/01/07(Wed) 18:28:57)
> [StructLayout(LayoutKind.Sequential)]
Packを指定するべきですね。

> int readCount = Marshal.SizeOf(typeof(Estimate));
C++側と一致してますか?
引用返信 編集キー/
■74537 / inTopicNo.3)  Re[2]: C++で書き出された構造体をC#で読み込む
□投稿者/ nobb (71回)-(2015/01/09(Fri) 09:18:34)
No74508 (PANG2 さん) に返信

>>[StructLayout(LayoutKind.Sequential)]
> Packを指定するべきですね。
Pack=2として設定したところ上手く取得できるようになりました。
C++側で__alignof(type)を使い2という数値を求めました。

検索途中で私と同じような事をしたいという内容の質問を見かけたのですが、
その中では「VC++でのデフォルトはPack=4」という記述をよく見かけます。
また、アライメントを変える方法として「#pragma pack(2)」や「__declspec(align(32))」を
使用すると書いてありましたが、C++プロジェクト内で検索してもそれらしい記述が見つかりませんでした。

そこで__alignofを使用しましたが、プロジェクトのプロパティに設定項目があったりするのでしょうか?


>> int readCount = Marshal.SizeOf(typeof(Estimate));
> C++側と一致してますか?
Packを指定する前は違っていました。
Pack=2とすると一致しました。
引用返信 編集キー/
■74578 / inTopicNo.4)  Re[3]: C++で書き出された構造体をC#で読み込む
□投稿者/ 774RR (211回)-(2015/01/09(Fri) 20:16:29)
既に pack を指定しないでセーブされたデータがあって、それを読む必然があるのか
pack を指定しないデータはまだ世に存在しないのか
で話は変わってくるわけだけど。

引用返信 編集キー/
■74614 / inTopicNo.5)  Re[3]: C++で書き出された構造体をC#で読み込む
□投稿者/ みい (14回)-(2015/01/13(Tue) 11:50:46)
No74537 (nobb さん) に返信
> 検索途中で私と同じような事をしたいという内容の質問を見かけたのですが、
> その中では「VC++でのデフォルトはPack=4」という記述をよく見かけます。
> また、アライメントを変える方法として「#pragma pack(2)」や「__declspec(align(32))」を
> 使用すると書いてありましたが、C++プロジェクト内で検索してもそれらしい記述が見つかりませんでした。
>
> そこで__alignofを使用しましたが、プロジェクトのプロパティに設定項目があったりするのでしょうか?
「C/C++」→「コード生成」→「構造体メンバーのアライメント」で
アライメントを設定できます。
引用返信 編集キー/
■74629 / inTopicNo.6)  Re[4]: C++で書き出された構造体をC#で読み込む
□投稿者/ nobb (72回)-(2015/01/15(Thu) 15:39:47)
No74578 (774RR さん) に返信
お返事大変遅くなり申し訳ありません。

> 既に pack を指定しないでセーブされたデータがあって、それを読む必然があるのか
今回に関して言えばpackがどこか(みいさんのご回答の通りの場所)で設定されていたので2が取り出せました。

引用返信 編集キー/
■74630 / inTopicNo.7)  Re[4]: C++で書き出された構造体をC#で読み込む
□投稿者/ nobb (73回)-(2015/01/15(Thu) 15:55:04)
No74614 (みい さん) に返信
お返事遅くなり申し訳ありません。

> 「C/C++」→「コード生成」→「構造体メンバーのアライメント」で
> アライメントを設定できます。
確認しましたところ、2バイトとして設定されているのが確認できました。
大変ありがとうございました。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -