如何将 cli::array 从本机代码转换为本机数组?

Posted

技术标签:

【中文标题】如何将 cli::array 从本机代码转换为本机数组?【英文标题】:How do I convert a cli::array to a native array from native code? 【发布时间】:2011-10-13 19:50:28 【问题描述】:

我正在围绕一个用 C++\CLI 编写的托管组件编写本机包装器。

我在托管代码中有以下功能:

array<Byte>^ Class::Function();

我想使用以下签名从本机 C++ 类公开此函数:

shared_array<unsigned char> Class::Function();

我已经从本机代码调用托管函数,但我不确定如何安全地将托管数组复制到非托管数组中。

gcroot<cli::array<System::Byte>^> managedArray = _managedObject->Function();

【问题讨论】:

你希望如何从函数中返回一个不可复制、不可移动的对象? 这是一个很好的观点 - 我想我实际上没有:S。应该是一个 shared_array。 我假设 shared_array 来自 boost,对吗? @R.MartinhoFernandes - 正确。出于这个问题的目的,尽管它可以很容易地成为unsigned char* 请注意,如果您使用的是 VC++ 2010(或 VC11 预览版),std::unique_ptr&lt;unsigned char[]&gt; 将是理想的高效返回类型。 【参考方案1】:

通常有两种方法:

    使用本机代码执行封送处理,这需要使用pin_ptr&lt;&gt;

     boost::shared_array<unsigned char> convert(array<unsigned char>^ arr)
     
         boost::shared_array<unsigned char> dest(new unsigned char[arr->Length]);
         pin_ptr<unsigned char> pinned = &arr[0];
         unsigned char* src = pinned;
         std::copy(src, src + arr->Length, dest.get());
         return dest;
     
    

    使用托管代码执行封送处理,这需要使用 Marshal 类:

     boost::shared_array<unsigned char> convert(array<unsigned char>^ arr)
     
         using System::Runtime::InteropServices::Marshal;
    
         boost::shared_array<unsigned char> dest(new unsigned char[arr->Length]);
         Marshal::Copy(arr, 0, IntPtr(dest.get()), arr->Length);
         return dest;
     
    

通常我更喜欢后一种方法,因为如果数组很大,前者会阻碍 GC 的有效性。

【讨论】:

我想我会再考虑后一种方法。由于我拥有托管代码的所有权,因此我可以简单地添加一个内部函数以将数据作为 shared_array 返回。 @ildjarn:由于std::copy 是一个模板,它不能与interior_ptr 一起正常工作吗? @Ben :我不这么认为,因为std::iterator_traits&lt;&gt; 没有专门针对interior_ptr&lt;T&gt;【参考方案2】:

看看pin_ptr,它可以让你将托管类的地址传递给非托管函数。

【讨论】:

以上是关于如何将 cli::array 从本机代码转换为本机数组?的主要内容,如果未能解决你的问题,请参考以下文章

如何将 pandas 数据框列转换为本机 python 数据类型?

将jdbc查询转换为JPA本机查询

如何将 IntPtr 转换为本机 C++ 对象

如何将 byte[] 转换为 bytebuffer 本机内存?

如何使用本机反应将时间戳值转换为特定时间格式?

如何将iOS反应本机模板转换为swift?