gpt4 book ai didi

c# - 从 IntPtr(16 位)数组复制到托管 ushort

转载 作者:太空狗 更新时间:2023-10-29 21:22:09 25 4
gpt4 key购买 nike

我有一个名为 rawbits 的 IntPtr,它指向一个 10MB 的数据数组,16 位值。我需要从中返回一个托管的 ushort 数组。下面的代码有效,但有一个额外的 BlockCopy 我想去掉。 Marshal.Copy 不支持 ushort。我能做什么? (仅供引用:rawbits 由视频帧抓取卡填充到非托管内存中)

    public const int width = 2056;
public const int height = 2048;
public const int depth = 2;
public System.IntPtr rawbits;

public ushort[] bits()
{
ushort[] output = new ushort[width * height];
short[] temp = new short[width * height];
Marshal.Copy(rawbits, temp, 0, width * height);
System.Buffer.BlockCopy(temp, 0, output, 0, width * height * depth);
return output;
}

以下问题中给出的建议没有帮助。 (编译器错误)。

C# Marshal.Copy Intptr to 16 bit managed unsigned integer array

[顺便说一句,短数组中确实有无符号的 16 位数据。 Marshal.Copy() 不遵守该标志,而这正是我想要的。但我宁愿不只是假装 short[] 是一个 ushort[] ]

最佳答案

选项 1 - 调用 CopyMemory :

[DllImport("kernel32.dll", SetLastError = false)]
static extern void CopyMemory(IntPtr destination, IntPtr source, UIntPtr length);

public static void Copy<T>(IntPtr source, T[] destination, int startIndex, int length)
where T : struct
{
var gch = GCHandle.Alloc(destination, GCHandleType.Pinned);
try
{
var targetPtr = Marshal.UnsafeAddrOfPinnedArrayElement(destination, startIndex);
var bytesToCopy = Marshal.SizeOf(typeof(T)) * length;

CopyMemory(targetPtr, source, (UIntPtr)bytesToCopy);
}
finally
{
gch.Free();
}
}

不便携,但性能不错。


选项 2 - unsafe和指针:

public static void Copy(IntPtr source, ushort[] destination, int startIndex, int length)
{
unsafe
{
var sourcePtr = (ushort*)source;
for(int i = startIndex; i < startIndex + length; ++i)
{
destination[i] = *sourcePtr++;
}
}
}

需要 unsafe在项目构建属性中启用的选项。


选项 3 - 反射(只是为了好玩,不要在生产中使用):

Marshal类内部使用 CopyToManaged(IntPtr, object, int, int)所有方法Copy(IntPtr, <array>, int, int)重载(至少在 .NET 4.5 中)。使用反射我们可以直接调用该方法:

private static readonly Action<IntPtr, object, int, int> _copyToManaged =
GetCopyToManagedMethod();

private static Action<IntPtr, object, int, int> GetCopyToManagedMethod()
{
var method = typeof(Marshal).GetMethod("CopyToManaged",
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
return (Action<IntPtr, object, int, int>)method.CreateDelegate(
typeof(Action<IntPtr, object, int, int>), null);
}

public static void Copy<T>(IntPtr source, T[] destination, int startIndex, int length)
where T : struct
{
_copyToManaged(source, destination, startIndex, length);
}

Marshal类内部可以更改,此方法不可靠,不应使用,尽管此实现可能最接近其他 Marshal.Copy()方法重载。

关于c# - 从 IntPtr(16 位)数组复制到托管 ushort,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28595903/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com