P/在结构体中调用定义长度的C char*数组

本文关键字:char 数组 定义 结构体 调用 | 更新日期: 2023-09-27 18:17:26

我已经找了一段时间,但没有找到文章提供这个问题的答案,所以希望它不是重复的。

我一直在用一个结构体做一些p/调用,这很好,但后来我看到了这个:

char* infoString[SIDTUNE_MAX_CREDIT_STRINGS];

其中SIDTUNE_MAX_CREDIT_STRINGS定义为10.

内联所有内容,结构成员定义为:

char* infoString[10]

现在,它与我在尝试解决这个问题时看到的其他问题略有不同。

char*数组包含指向其他C字符串的指针。

在这个特定的例子中,只有3个索引被使用,其余的被保留。索引如下:

  • infoString[0] =歌曲标题

  • infoString[1] =艺人名

  • infoString[2] = Copyright/Publisher.

我如何p/调用它,以一种我可以从c#访问每个字符串的方式?让c++函数单独返回每一个是不可能的。

P/在结构体中调用定义长度的C char*数组

假设函数类似于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/Invoke签名:

[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;
};