将字节数组从 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# 3D 数组作为 1D 字节数组传递给 C++ 库

将字节数组从 C# 传递到 C++ DLL 作为 char*

使用 Dllimport 将一个非常大的字符串作为字节数组从 C++ 传递到 C#

将二维数组从 C# 传递到 C++

如何通过引用从 c# 到 c++ 传递字节数组