以 uint16_t* 形式访问 .NET ushort[] 数组而不复制

Access .NET ushort[] array as uint16_t* without copying

将 ushort[] 从 c# 转换为 c++/cli 转换为 c++ 时,是否必须复制所有数据?或者我可以投指针吗?

PreprocessorWrapper::Function1(ImageData^ rawImage)
{
    array<unsigned short>^ rawDataTemp = rawImage->RawData;
    bayer_raw_image* inputImage = new bayer_raw_image();
    inputImage->raw_data = (uint16_t*)rawDataTemp; //error is here
}

这是我遇到的错误

error C2440: 'type cast' : cannot convert from 'cli::array<Type> ^' to 'uint16_t 

这是 C# class

public class ImageData
    {
       public int WidthColumns { get; set; }
        public int HeightLines { get; set; }
        public ushort[] RawData { get; set; }
        public ushort BitDepth { get; set; }
    }

c++ class

typedef struct
{
    uint16_t width;
    uint16_t height;
    uint16_t* raw_data;
    uint16_t bit_depth;
} bayer_raw_image;

不,您不必这样做,但您必须固定它,因为允许 GC 在垃圾收集期间移动内存中的托管对象。

array<uint16_t>^ rawDataTemp = rawImage->RawData;
pin_ptr<uint16_t> rawDataPinned = &rawDataTemp[0];
bayer_raw_image* inputImage = new bayer_raw_image();
inputImage->raw_data = rawDataPinned;

你应该rawDataPinned超出范围后使用指针,因为数据将不再被固定并且会被移动通过 GC 压缩。这是一个等待发生的讨厌的错误。

如果您需要长期固定,请使用固定 GCHandle:

GCHandle::Alloc(rawImage->RawData, GCHandleType::Pinned)

它通过handle->AddrOfPinnedObject().ToPointer()为第一个数组项提供void*
使用后别忘了Free()

这比 pin_ptr 更重量级,因为它需要在 GC 中注册一个句柄,而 pin_ptr 只有在您的对象被固定时发生收集时才会被 GC 注意到 -它尽可能轻便。