おそらく考えている方法で関数から配列を返すことはできませんが、配列へのポインターを返すことはできます。データを適切な C# 型に適切にマーシャリングできるように、配列の長さも返す必要があります。これには、関数に渡されたパラメーターを介して情報を返す代わりに、関数のシグネチャを少し変更する必要があります。
extern "C" EXPORT_API bool GetCharacterPositions(CharacterInformation** data, int *length)
{
CharacterInformation *characterInformationArray = new CharacterInformation[arraysize];
// initialize contents of array.
// ... snip ...
*length = arraysize;
*data = characterInformationArray;
return true;
}
この場合、デフォルトのコンストラクターを追加して、CharacterInformation
2 フェーズの初期化 (つまり、Init()
関数) を使用する必要があります。
非静的ローカル変数へのポインターまたは参照を返すべきではないことに注意してください。変数の内容は、スコープ外になると (つまり、関数が戻ると) 破棄されるためです。
データをマーシャリングするには、次のようなことを試すことができます。これはテストされていませんが、正しい方向へのプッシュを与えるはずです。
[DllImport("Dllname.dll",
CallingConvention = CallingConvention.Winapi,
CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.I1)]
public static extern bool GetCharacterPositions(out IntPtr arrayPtr, out int size);
public static List<CharacterInformation> GetCharacterPositions()
{
var arrayValue = IntPtr.Zero;
var size = 0;
var list = new List<CharacterInformation>();
if ( !GetCharacterPositions(out arrayValue, out size))
{
return list;
}
var dataEntrySize = Marshal.SizeOf(typeof(CharacterInformation));
for ( var i = 0; i < size; i++)
{
var cur = (CharacterInformation )Marshal.PtrToStructure(arrayValue, typeof(CharacterInformation ));
list.Add(cur);
arrayValue = new IntPtr(arrayValue.ToInt32() + dataEntrySize);
}
return list;
}
C++ でデータを適切に削除するには、追加の呼び出しを追加する必要があります。そうしないと、メモリ リークが発生します。