構造体と参照

概要

構造体と参照を使ったデータのやりとり

構造体と参照

構造体の場合、参照(ポインタ)で渡すこととなりますが
データ構造をC#とC++で一致させる必要があります。
C++側の#pragma pack(1)の指定と、[StructLayout(LayoutKind.Sequential, Pack=1)]
その点を気をつけましょう。

  • 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 MyPicture
    {
    	BYTE ColorDepth;
    	int32_t Width;
    	int32_t Height;
    	bool HasAlpha;
    };
    #pragma pack()
    // pragma pack は元へと戻った
    
    // 構造体受け取りと値の代入
    extern "C" void DLLEXPORT dllStructPointer(MyPicture *pMyPicture) {
    
    	pMyPicture->Width = 100;
    	pMyPicture->Height = 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;
                public Int32 Width;
                public Int32 Height;
                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.Width},{pic.Height},{pic.ColorDepth},{pic.HasAlpha}");
    
                Console.ReadKey();
            }
        }
    }