要PInvoke的字符**的类型
本文关键字:类型 PInvoke 字符 | 更新日期: 2023-09-27 17:59:24
考虑以下C函数:
void get_lib_version(const char **ver_string);
如何使用PInvoke正确整理?文档中说它返回一个指向静态字符串的指针。我以为这样就可以了:
[DllImport(DllPath, CallingConvention = CallingConvention.Cdecl)]
public static extern int get_lib_version(StringBuilder version);
但我得到的只是胡言乱语。
你必须帮忙阻止执法官这么做。这需要将参数声明为原始指针,而不是字符串:
[DllImport(DllPath, CallingConvention = CallingConvention.Cdecl)]
public static extern int get_lib_version(out IntPtr version);
你必须做额外的步骤来将指针转换为字符串:
public string GetLibraryVersion() {
IntPtr strptr;
get_lib_version(out strptr);
return Marshal.PtrToStringAnsi(strptr);
}
编写一个小测试程序来验证这个假设。调用GetLibraryVersion()十亿次。如果内存使用率没有爆炸式增长,那么你就很好。
根据这个答案,当您将某个东西封送为string
时,PInvoke会对如何释放它做出各种假设。请注意,这是一个const char *
;它在某个地方是一个常量字符串。它永远不需要释放!
显然,处理这个问题的方法是
马歇尔作为
IntPtr
。使用
Marshall.PtrToStringAnsi()
将结果复制到C#字符串中。
我设法使其正常工作:
[DllImport(DllPath, CallingConvention = CallingConvention.Cdecl)]
private static extern int get_lib_version(ref IntPtr version);
public static string GetLibVersion()
{
var ptrVersion = IntPtr.Zero;
get_lib_version(ref ptrVersion);
var version = Marshal.PtrToStringAnsi(ptrVersion);
return version;
}