将字节数组从 Unity C# 传递到 C++ 库方法
Posted
技术标签:
【中文标题】将字节数组从 Unity C# 传递到 C++ 库方法【英文标题】:Passing a byte array from Unity C# into a C++ library method 【发布时间】:2015-03-20 16:14:15 【问题描述】:我有一个 C++ 库方法,我想从 Unity C# 脚本中调用它。
我知道有三个关键步骤。首先,将 C++ 方法声明为extern "C"
。其次,在相应的C# extern 方法声明之前使用[DllImport('foobar')]
。第三,以lib前缀命名库文件(例如libfoobar.so
)并将其放置在Unity插件文件夹中。
到目前为止一切顺利——如果我只是将简单的参数类型(如 int
)从 C# 传递到 C++。但是,要传递 byte[]
参数,我需要考虑 C# 和 C++ 处理内存和指针的不同方式。我还没有找到一个明确的例子来说明如何做到这一点。
我的问题:如何将 byte[]
从 Unity C# 脚本传递到外部 C++ 库方法?
【问题讨论】:
这是 P/Invoke 方法吗?您还可以使用 C++ CLI。我听说 C++ CLI 给了你更多的控制权。但是,我从来没有做过。带上一粒盐。 不要忘记来自 DllImport 的CallingConvention = CallingConvention.Cdecl
,因为您使用的是 extern "C"
@Golazo - 不使用 P/Invoke,只是将 C++ extern 声明为 extern "C"
并通过 DllImport
属性从 C# 引用它。不需要 P/Invoke,至少不需要传入简单的参数类型。
这是托管 C++ 吗?因为据我所知,如果没有 P/Invoke、C++ CLI 或 COM,您无法在 C# 中调用本机 C++ 代码
你可能想看看这个:snowbolt.com/index.php/blog/28-tech/91-pinvoke
【参考方案1】:
您必须更改方法定义以获取 IntPtr。这是定义指向非托管内存的指针的 C# 方法。要创建此指针,请使用Marshal.AllocHGlobal()
,然后使用Marshal.Copy()
将数据复制到它。
示例(未测试):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace Assets.Scripts
public class DLLCall
[DllImport("thedll")]
public static extern void TheCall(IntPtr byteArray, int size);
public void PerformCall(byte[] data)
IntPtr unmanagedArray = Marshal.AllocHGlobal(data.Length);
Marshal.Copy(data, 0, unmanagedArray, data.Length);
TheCall(unmanagedArray, data.Length);
Marshal.FreeHGlobal(unmanagedArray);
请注意,您必须使用Marshal.FreeHGlobal
手动释放非托管内存。在此之后,内存不再有效,因此 C++ 库不能再使用它。如果稍后需要访问数组,请删除 FreeHGlobal
调用,并确保在库不再需要访问内存后删除内存。
【讨论】:
【参考方案2】:为我工作:
团结一致:
[DllImport ("dllplugin")]
public static extern void Method (byte[] bytes);
在 c++ 插件中
#define EXPORT_API __declspec(dllexport)
extern "C" void EXPORT_API Method(unsigned char* bytes)
【讨论】:
我像这样将字节数组从统一传递到 c++ 插件,它工作正常,但发送 17 个字节到其他地方(C++)只接收 4 个字节。这是什么原因?请帮助跨度> @Rajesh 这里有同样的问题。将 4096 个字节从 C# 传递到 C++,但在 C++ 端,根据sizeof(bytes)
,数组只有 8 个字节。
此外,将其更改为无符号 char*
而不是 char
只会使 sizeof 为 8,而数组的长度为 1。
我知道这是一篇旧帖子,但在 C++ 中,sizeof(bytes) 只会给你指针的大小而不是它指向的数据的大小,请参阅这篇文章的第一个答案:***.com/questions/399003/…。如果你想这样做,你还需要传递 C# 字节数组的长度。
我编辑了函数的答案,使其也将数组的长度作为参数。请注意,在这种情况下,我们不需要元素大小,因为我们知道它是每个元素一个字节。在 c++ 端,缓冲区的开头是字节,缓冲区的结尾是字节 + 长度。以上是关于将字节数组从 Unity C# 传递到 C++ 库方法的主要内容,如果未能解决你的问题,请参考以下文章
将字节数组从 c++ 传递到 c# 程序集都有哪些不同的方法?
将字节数组从 C# 传递到 C++ DLL 作为 char*