Mik*_*ron 10 c c# string pinvoke marshalling
我正在接受带有char**(即指向字符串的指针)的代码:
int DoSomething(Whatever* handle, char** error);
Run Code Online (Sandbox Code Playgroud)
基本上,它需要处理其状态,如果出现问题,它会返回错误代码和可选的错误消息(内存分配在外部并通过第二个函数释放.这部分我已经发现:)).
但是,我不确定如何处理C#.我目前有什么:
[DllImport("mydll.dll", CallingConvention = CallingConvention.Cdecl)]
private static unsafe extern int DoSomething(IntPtr handle, byte** error);
public static unsafe int DoSomething(IntPtr handle, out string error) {
byte* buff;
int ret = DoSomething(handle, &buff);
if(buff != 0) {
// ???
} else {
error = "";
}
return ret;
}
Run Code Online (Sandbox Code Playgroud)
我已经戳了戳,但我无法弄清楚如何把它变成一个byte[]适合喂食的UTF8Encoding.UTF8.GetString()
我是在正确的轨道上吗?
编辑:为了更明确,库函数分配内存,必须通过调用另一个库函数释放.如果一个解决方案没有给我一个指针,我可以释放,解决方案是不可接受的.
额外问题:如上所述,此库使用UTF-8作为其字符串.我是否需要在P/Invokes中做任何特殊操作,或者仅string用于正常const char*参数?
您应该能够使用 aref string并让运行时默认编组器为您处理此转换。您可以提示参数上的字符宽度,[MarshalAs(UnmanagedType.LPStr)]以确保您使用的是 8 位字符。
由于您有一个特殊的释放方法要调用,因此您需要保留指针,就像您在问题示例中所示的那样。
我是这样写的:
[DllImport("mydll.dll", CallingConvention = CallingConvention.Cdecl)]
private static unsafe extern int DoSomething(
MySafeHandle handle, void** error); // byte** should work, too, I'm just lazy
Run Code Online (Sandbox Code Playgroud)
然后就可以得到一个字符串:
var errorMsg = Marshal.PtrToStringAnsi(new IntPtr(*error));
Run Code Online (Sandbox Code Playgroud)
和清理:
[DllImport("mydll.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern int FreeMyMemory(IntPtr h);
// ...
FreeMyMemory(new IntPtr(error));
Run Code Online (Sandbox Code Playgroud)
现在我们有了编组错误,所以只需返回它即可。
return errorMsg;
Run Code Online (Sandbox Code Playgroud)
另请注意MySafeHandle类型,它将继承自System.Runtime.InteropServices.SafeHandle. 虽然不是严格需要的(您可以使用 IntPtr),但它在与本机代码互操作时为您提供更好的句柄管理。在这里阅读:http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.safehandle.aspx。
| 归档时间: |
|
| 查看次数: |
1772 次 |
| 最近记录: |