アンマネージ dll との間でデータを保存および取得しようとしています。構造体を可能な限り単純化することで問題を絞り込もうとしましたが、ここに私が行き着いているものがあります:
構造定義
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public class MyStruct
{
private UInt32 size;
public UInt16 SomeData;
public MyStruct()
{
size = (UInt32)Marshal.SizeOf(this);
this.SomeData = 66; //just put any non 0 value for test
}
}
DLL のインポート:
[DllImport(MY_DLL, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
[return:MarshalAs(UnmanagedType.U1)]
public static extern bool SetData(ref MyStruct ms);
[DllImport(MY_DLL, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern IntPtr GetData();
関数呼び出し:
MyStruct ms_in = new MyStruct();
bool b = Wrapper.SetData(ref ms_in);
IntPtr ptr = Wrapper.GetData();
MyStruct ms_out = (MyStruct)Marshal.PtrToStructure(ptr, typeof(MyStruct));
十分に単純だと思います。ほとんどのコードで実際に行ったのと同じ dll の別の構造体定義から構造体レイアウト属性を貼り付けただけなので、charset とパッキングが問題ないことはわかっています。
ms_out の内容を読み取ると、ゴミ (ランダムな大きな数字) でいっぱいになります。
試行錯誤してようやく私の質問に対する答えを見つけましたが、あまり理解できません。作業バージョンは次のとおりです。
[DllImport(MY_DLL, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
[return:MarshalAs(UnmanagedType.I1)]
public static extern bool SetData( [In, MarshalAs(UnmanagedType.LPStruct)] MyStruct ms);
ref を [In, MarshalAs(UnmanagedType.LPStruct)] に置き換えるとうまくいきましたが、なぜですか?
回答ありがとうございます。コーディングをお楽しみください。