関数が のようなものであると仮定すると、は の配列を持つものとしてGetSongInfo(int songID, LPInfostring songinfo)
定義できます。ただし、呼び出し元の関数は、返された文字列に割り当てられたメモリを解放することを期待する可能性があるため、メモリ リークに注意する必要があります。struct
IntPtr
ターゲット.h:
typedef struct SongInfo
{
char* infoString[10];
} *LPSongInfo;
extern "C" __declspec(dllexport) int GetSongInfo(int songID, LPSongInfo info);
ターゲット.c:
extern "C" __declspec(dllexport) int GetSongInfo(int songID, LPSongInfo demo)
{
demo->infoString[0] = "Hello world";
demo->infoString[1] = "Hello 1";
demo->infoString[2] = "Hello 2";
return TRUE;
}
P/インボーク署名:
[DllImport("PInvokeDll.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern int GetSongInfo(int songID, out SongInfo ts);
[StructLayout(LayoutKind.Sequential)]
struct SongInfo
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
public IntPtr[] infoString;
};
使用例:
SongInfo siStruct;
var num2 = GetSongInfo(101, out siStruct);
// copy the results to managed memory
var results = new string[10];
for (int i = 0; i < 10; i++)
{
if (siStruct.infoString[i] != IntPtr.Zero)
{
// if these were Unicode strings, this would change to PtrToSTringUni
results[i] = Marshal.PtrToStringAnsi(siStruct.infoString[i]);
}
}
// results now holds the .Net strings
// if there is an expectation of the caller to free the struct
// strings, that should happen now
メモリを割り当てない関数の代わりに、次のような構造体を使用して文字列を自動的にマーシャリングできます。ただし、アンマネージ メモリは無条件に解放されますが、これは望ましい場合と望ましくない場合があります。
[StructLayout(LayoutKind.Sequential)]
struct SongInfo2
{
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.LPStr, SizeConst = 10)]
public string[] infoString;
};