構造体内の固定配列

概要

構造体内に固定配列を持ったデータのやりとり

構造体の構造体

構造体内に固定配列を持ったデータを持っている場合
[MarshalAs(UnmanagedType.ByValArray, SizeConst=**配列のサイズ**)] を使います。

  • C++側のソース

    Dll1.dllとしてコンパイル
    #include <windows.h>
    #include <cstddef>
    #include <iostream>
    
    using namespace std;
    
    #define DLLEXPORT __declspec(dllexport) WINAPI
    
    // ★C#側とC++側のデータの並びとサイズと一致させるためには、「pragma pack」の指定が必須
    #pragma pack(1)
    struct TMyPicture
    {
    	BYTE ColorDepth;
    	int32_t Resolution[2];
    	bool HasAlpha;
    };
    #pragma pack()
    // pragma pack は元へと戻った
    
    // 構造体受け取りと値の代入
    extern "C" void DLLEXPORT dllStructPointer(TMyPicture *pMyPicture) {
    
    	pMyPicture->Resolution[0] = 100;
    	pMyPicture->Resolution[1] = 200;
    	pMyPicture->ColorDepth = 32;
    	pMyPicture->HasAlpha = true;
    }
    
  • C#側のソース

    test1.cs
    using System;
    using System.Runtime.InteropServices;
    
    namespace test1
    {
        internal class Program
        {
            [DllImport("Dll1.dll")]
            static extern void dllStructPointer(ref MyPicture pic);
    
    
            // この行を忘れないこと。原則Sequentialとして、Packも1とする
            [StructLayout(LayoutKind.Sequential, Pack=1)]
            struct MyPicture
            {
                public byte ColorDepth;
    
                // 固定配列で配列のサイズが2である
                [MarshalAs(UnmanagedType.ByValArray, SizeConst=2)]
                public Int32[] Resolution;
    
                public bool HasAlpha;
            }
    
    
            static void Main(string[] args)
            {
                MyPicture pic = new MyPicture();
                var structSize = Marshal.SizeOf(pic);
                Console.WriteLine(structSize);
    
                dllStructPointer(ref pic);
    
                Console.WriteLine($"{pic.Resolution[0]},{pic.Resolution[1]},{pic.ColorDepth},{pic.HasAlpha}");
    
                Console.ReadKey();
            }
        }
    }