在编组C#一个char ** [英] Marshalling a char** in C#

查看:141
本文介绍了在编组C#一个char **的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我与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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆