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

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

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

固定長配列を含む構造体のマーシャリング

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

■87194 / inTopicNo.1)  固定長配列を含む構造体のマーシャリング
  
□投稿者/ mbox (3回)-(2018/04/21(Sat) 06:25:18)

分類:[.NET 全般] 

以下のような構造体Fをマーシャリングしたいのですが、
fixed配列aが期待通りマーシャリングされません。
なぜこのような現象になるのでしょうか?

fixed配列ではなく、普通の配列にしてMarshalAs属性を付けるとか、
bを消すとかすると正しくマーシャリングされるのですが、
fixed配列のまま、正しくマーシャリングするにはどうすればよいのでしょうか?

(.net 4.0, xp 32bit)


using System;
using System.Runtime.InteropServices;

unsafe class Program
{
    struct F
    {
        public fixed byte a[2];

        //[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
        //public byte[] a;

        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 3)]
        public string b;
    }

    static void Main()
    {
        var buf = new byte[] { 1, 2, 65, 66, 0 };
        fixed (byte* p = buf)
        {
            F f = (F)Marshal.PtrToStructure((IntPtr)p, typeof(F));
            Console.WriteLine("{0} {1}", f.a[0], f.a[1]); //1 2でなく、1 0になるのはなぜ?
            Console.WriteLine(f.b); //AB
        }
    }
}

引用返信 編集キー/
■87195 / inTopicNo.2)  Re[1]: 固定長配列を含む構造体のマーシャリング
□投稿者/ Azulean (947回)-(2018/04/21(Sat) 19:33:43)
No87194 (mbox さん) に返信
> fixed配列ではなく、普通の配列にしてMarshalAs属性を付けるとか、
> bを消すとかすると正しくマーシャリングされるのですが、
> fixed配列のまま、正しくマーシャリングするにはどうすればよいのでしょうか?

できないのでは?という印象を持っています。

コンパイルしてできたバイナリを IL 逆アセンブラーに処理させると、フィールド a に対する特殊な構造体ができていることを確認できると思います。
C# コードに書き直した際のイメージとしては以下のような感じです。
(実際にはいくつか属性がついています)

struct F
{
  [StructLayout(LayoutKind.Sequential, Size=2)]
  sturct <a>__FixedBuffer
  {
     public byte FixedElementField;
  }
  public <a>__FixedBuffer a;
  public string b;
}

ただ、PtrToStructure だと、その FixedElementField の位置に値を設定するものの、残りのバイトは構造体にフィールドがないので無視されるようです。
fixed の実装と、PtrToStructure の実装がこうなっている以上は諦められた方が早いかと思います。

引用返信 編集キー/
■87197 / inTopicNo.3)  Re[2]: 固定長配列を含む構造体のマーシャリング
□投稿者/ mbox (4回)-(2018/04/22(Sun) 10:36:04)
No87195 (Azulean さん) に返信
> ただ、PtrToStructure だと、その FixedElementField の位置に値を設定するものの、残りのバイトは構造体にフィールドがないので無視されるようです。
> fixed の実装と、PtrToStructure の実装がこうなっている以上は諦められた方が早いかと思います。

まあ諦めるしかないのかな、とも思いますが、
bを消すと、aに対して自動生成される特殊な構造体は全く変わらないのに、
正しくマーシャリングされる、ということから、
全くできないわけでもなく、イマイチ諦めきれない感じです。

PtrToStructureの中身を見れば何か分かるかな、と思って、
https://referencesource.microsoft.com/#mscorlib/system/runtime/interopservices/marshal.cs,f5afb57bc99ab27c
を見ても、externのPtrToStructureHelperを呼んでいるだけで、
この中身が見れないので何も分かりませんでした。

引用返信 編集キー/

このトピックをツリーで一括表示


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

このトピックに書きこむ