在编组C#一个char ** [英] Marshalling a char** in C#
问题描述
我与code,需要一个的char **接口
(也就是一个指向字符串):
I am interfacing with code that takes a char**
(that is, a pointer to a string):
int DoSomething(Whatever* handle, char** error);
基本上,它需要一个手柄,它的状态,如果出现错误,则返回错误code和可选的错误信息(内存分配外,并与第二功能中解脱出来,这部分我已经figued了:))。
Basically, it takes a handle to its state, and if something goes wrong, it returns an error code and optionally an error message (the memory is allocated externally and freed with a second function. That part I've figued out :) ).
我,但是,我不确定如何处理在C#。我现在什么:
I, however, am unsure how to handle in in C#. What I have currently:
[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;
}
我戳左右,但我无法弄清楚如何把它转换成一个字节[]
,适合喂养 UTF8Encoding .UTF8.GetString()
我在正确的轨道上吗?
编辑:为了更明确,库函数的分配内存,它必须通过调用另一个库函数被释放。如果解决方案不留我一个指针,我可以自由的,解决的办法是不可接受的。
To make more explicit, the library function allocates memory, which must be freed by calling another library function. If a solution does not leave me with a pointer I can free, the solution is unacceptable.
奖金的问题:正如上面暗示,该库使用UTF-8为它的字符串。我需要做什么特别的事情在我的P /调用,或者只是使用字符串
正常为const char *
参数?
Bonus question: As implied above, this library uses UTF-8 for its strings. Do I need to do anything special in my P/Invokes, or just use string
for normal const char*
parameters?
推荐答案
<击>您应该只可以使用 REF字符串
并运行默认编组取关心这个转换为你的。你可以暗示该参数的字符宽度与 [的MarshalAs(UnmanagedType.LPStr)]
,以确保您使用的是8位字符。击>
You should just be able to use a ref string
and have the runtime default marshaller take care of this conversion for you. You can hint the char width on the parameter with [MarshalAs(UnmanagedType.LPStr)]
to make sure that you are using 8-bit characters.
既然你有一个特殊的释放方法来调用,你需要保持指针,就像你已经在你的问题的示例所示。
Since you have a special deallocation method to call, you'll need to keep the pointer, like you've already shown in your question's example.
下面就是我会写:
[DllImport("mydll.dll", CallingConvention = CallingConvention.Cdecl)]
private static unsafe extern int DoSomething(
MySafeHandle handle, void** error); // byte** should work, too, I'm just lazy
然后你就可以得到一个字符串:
Then you can get a string:
var errorMsg = Marshal.PtrToStringAnsi(new IntPtr(*error));
和清理:
[DllImport("mydll.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern int FreeMyMemory(IntPtr h);
// ...
FreeMyMemory(new IntPtr(error));
和现在我们有编组的错误,所以才返回。
And now we have the marshalled error, so just return it.
return errorMsg;
另外要注意的 MySafeHandle
类型,它会从 System.Runtime.InteropServices.SafeHandle
继承。虽然不是必需的(你可以使用IntPtr的),它与本地code interoping时给你一个更好的处理管理。读到这里:的http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.safehandle.aspx.
Also note the MySafeHandle
type, which would inherit from System.Runtime.InteropServices.SafeHandle
. While not strictly needed (you can use IntPtr), it gives you a better handle management when interoping with native code. Read about it here: http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.safehandle.aspx.
这篇关于在编组C#一个char **的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!