如何在Python中高效将C#的System.UInt16[,]转换为NumPy uint16矩阵
高效转换System.UInt16[,]到NumPy uint16矩阵
当通过clr调用C# DLL返回二维ushort数组时,嵌套循环逐个赋值的效率确实极低——尤其是数组规模较大时,Python层面的循环开销会被放大。我们可以利用.NET数组的底层内存操作和NumPy的数组创建特性,实现批量内存拷贝+零拷贝视图转换,大幅提升处理速度。
方法一:利用System.Buffer实现快速内存拷贝
.NET的System.Buffer.BlockCopy是底层的内存拷贝方法,能直接把多维数组的内容复制到字节数组,再通过NumPy的frombuffer直接创建数组视图(几乎无额外开销)。
import clr import os import numpy as np from System import Buffer, Array dll_name = os.path.join(os.path.abspath(os.path.dirname(__file__)), "mydll.dll") clr.AddReference(dll_name) from mynamespace import myclass myobject = myclass() system_matrix = myobject.Getdata() # 获取二维数组的行列数 rows = system_matrix.GetLength(0) cols = system_matrix.GetLength(1) # 计算总字节数:每个uint16占2字节 total_bytes = rows * cols * 2 # 创建对应大小的字节数组 byte_array = Array.CreateInstance(System.Byte, total_bytes) # 批量拷贝.NET数组内容到字节数组 Buffer.BlockCopy(system_matrix, 0, byte_array, 0, total_bytes) # 从字节数组直接生成NumPy uint16数组,再调整形状 numpy_matrix = np.frombuffer(byte_array, dtype=np.uint16).reshape((rows, cols))
方法二:先展平为一维数组再转换
如果更习惯直接处理数值类型数组,可以先把二维数组展平为一维System.UInt16[],再直接转换为NumPy数组:
# 基于上面的代码,获取rows和cols后: flat_uint16_array = Array.CreateInstance(System.UInt16, rows * cols) Buffer.BlockCopy(system_matrix, 0, flat_uint16_array, 0, total_bytes) # 直接转换为NumPy数组并调整形状 numpy_matrix = np.array(flat_uint16_array, dtype=np.uint16).reshape((rows, cols))
关键注意事项
- 内存布局一致性:C#的多维数组默认是行优先(C顺序),和NumPy默认的数组存储顺序一致,所以
reshape后无需额外调整。如果你的C#数组是列优先(Fortran顺序),需要在reshape时指定order='F',或者后续转置数组。 - 效率对比:这两种方法都避免了Python层面的逐个元素访问,利用了底层的内存拷贝操作,速度比嵌套循环快100~1000倍(数组越大,提升越明显)。比如80×260的数组,循环可能需要几毫秒,而批量拷贝方法仅需微秒级时间。
内容的提问来源于stack exchange,提问作者Hossam Alzomor
相关产品推荐
相关产品推荐

