This question already has answers here:
marshalling a struct containing string
(2个答案)
6年前关闭。
我已经寻找了一段时间,但是没有找到任何文章可以提供答案,因此希望它不是重复的。
我一直在使用结构进行一些P / Invoking,这很不错,而且还不错,但是后来我看到了:
其中SIDTUNE_MAX_CREDIT_STRINGS定义为10。
因此,内联所有内容,将struct成员定义为:
现在,这里与我尝试解决该问题所遇到的其他问题略有不同。
char *数组包含指向其他C字符串的指针。
在这种特定情况下,仅使用3个索引,其余保留。索引如下:
infoString [0] =歌曲标题
infoString [1] =艺术家名称
infoString [2] =版权/发布者。
我将如何以一种可以从C#访问每个字符串的方式P /调用它?使C ++函数分别返回每个函数不是一个选择。
target.c:
P /调用签名:
使用示例:
作为不分配内存的函数的替代方法,可以使用如下结构来自动封送字符串。但是,它将无条件地释放非托管内存,这可能是不希望的。
(2个答案)
6年前关闭。
我已经寻找了一段时间,但是没有找到任何文章可以提供答案,因此希望它不是重复的。
我一直在使用结构进行一些P / Invoking,这很不错,而且还不错,但是后来我看到了:
char* infoString[SIDTUNE_MAX_CREDIT_STRINGS];
其中SIDTUNE_MAX_CREDIT_STRINGS定义为10。
因此,内联所有内容,将struct成员定义为:
char* infoString[10]
现在,这里与我尝试解决该问题所遇到的其他问题略有不同。
char *数组包含指向其他C字符串的指针。
在这种特定情况下,仅使用3个索引,其余保留。索引如下:
infoString [0] =歌曲标题
infoString [1] =艺术家名称
infoString [2] =版权/发布者。
我将如何以一种可以从C#访问每个字符串的方式P /调用它?使C ++函数分别返回每个函数不是一个选择。
最佳答案
假设函数类似于GetSongInfo(int songID, LPInfostring songinfo)
,则可以将struct
定义为具有IntPtr
数组。但是,您将必须注意内存泄漏,因为调用函数可能希望您释放为返回的字符串分配的内存。
target.h:
typedef struct SongInfo
{
char* infoString[10];
} *LPSongInfo;
extern "C" __declspec(dllexport) int GetSongInfo(int songID, LPSongInfo info);
target.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;
};
07-26 09:28