在P/Invoke中为固定字符串传递什么? [英] What to pass for pinned string in P/Invoke?

查看:84
本文介绍了在P/Invoke中为固定字符串传递什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设此C函数:

void do_something(const char* str)

它将字符串存储在以后参考的某个地方.

It stores the string somewhere for later reference.

此外,我在C#中具有此签名以调用此函数:

Furthermore, I have this signature in C# to call this function:

[DllImport("NativeLib")]
static extern void do_something(string str);

现在,将字符串传递给此方法时我需要做什么:

Now, what do I need to do when passing a string to this method:

  • 我是否需要固定字符串(使用GCHandle.Alloc())(或者编组器正在创建副本)?
  • 如果确实需要固定它,是否传递原始"字符串(即传递给GCHandle.Alloc()的字符串)?还是我需要传递GCHandle.AddrOfPinnedObject()的返回值?
  • 在这种情况下,string是否是正确的数据类型(对于do_something)?还是应该改用IntPtr?
  • Do I need to pin the string (with GCHandle.Alloc()) (or is the marshaller creating a copy)?
  • If I do need to pin it, do I pass the "original" string (i.e. the string I passed to GCHandle.Alloc())? Or do I need to pass the return value of GCHandle.AddrOfPinnedObject()?
  • Is string the correct data type (for do_something) in this case? Or should I use IntPtr instead?

推荐答案

通过互操作边界存储指针是一个非常糟糕的主意,请尽一切可能修改C代码以代替字符串.

Storing pointers through an interop boundary is a Really Bad Idea, do everything you can to modify the C code to make a copy of the string instead.

按照建议的答案固定字符串是行不通的,pinvoke编组必须将字符串转换为char *,并在进行本机调用后释放转换后的字符串,从而使指针无效.您必须自己编组弦线.将参数声明为IntPtr并使用Marshal.StringToHGlobalAnsi()创建指针值.

Pinning the string as suggested in the upvoted answer isn't going to work, the pinvoke marshaller must convert the string to char* and releases that converted string after making the native call, invalidating the pointer. You must marshal the string yourself. Declare the argument as IntPtr and use Marshal.StringToHGlobalAnsi() to create the pointer value.

或使用Marshal.StringToCoTaskMemAnsi(),它从COM堆分配.这是您真正的问题,没有释放字符串的好方案. C代码无法释放字符串,因为它不知道它是如何分配的.您的C#代码无法释放字符串,因为它不知道何时使用指针完成C代码.这就是为什么复制字符串如此重要的原因.如果只进行几次调用,就可以忍受内存泄漏.

Or use Marshal.StringToCoTaskMemAnsi(), it allocates from the COM heap. Which is your real problem, there is no great scenario to release the string. The C code cannot release the string because it doesn't know how it was allocated. Your C# code cannot release the string because it doesn't know when the C code is done with the pointer. This is why copying the string is so important. You can live with the memory leak if you make this call only a few times.

这篇关于在P/Invoke中为固定字符串传递什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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