如何快速将C#的System.UInt16[,]二维数组转换为Python列表?
快速转换C# UInt16二维数组到Python列表的方案
核心思路:直接操作连续内存块
C#的System.UInt16[,]是行优先连续存储的二维数组,无需逐元素遍历,直接读取整块内存是效率最高的方式。
方法1:基于pythonnet的内存拷贝实现
如果使用pythonnet(clr模块)调用C# DLL,结合.NET的Marshal类直接复制内存到Python,再转成目标格式:
import clr import numpy as np from System import UInt16 from System.Runtime.InteropServices import Marshal # 假设已获取C#二维数组:csharp_array = ... rows = csharp_array.GetLength(0) cols = csharp_array.GetLength(1) # 获取数组内存起始指针,计算总字节数 ptr = Marshal.UnsafeAddrOfPinnedArrayElement(csharp_array, 0) total_bytes = rows * cols * 2 # UInt16占2字节 # 批量读取内存到字节对象 bytes_data = Marshal.Copy(ptr, bytearray(total_bytes), 0, total_bytes) # 转numpy数组并重塑形状,最后转Python列表 np_array = np.frombuffer(bytes_data, dtype=np.uint16).reshape(rows, cols) python_list = np_array.tolist()
方法2:用ctypes直接映射内存(已知内存地址时)
如果能从C# DLL获取数组的原始内存地址,可通过ctypes直接映射内存,实现零拷贝转换:
import ctypes import numpy as np # 假设已获取数组内存地址ptr(整数)、行数rows、列数cols ptr = ... rows = ... cols = ... # 用ctypes创建指向目标内存的数组 c_array = (ctypes.c_uint16 * (rows * cols)).from_address(ptr) # 映射为numpy数组并重塑,最后转列表 np_array = np.ctypeslib.as_array(c_array).reshape(rows, cols) python_list = np_array.tolist()
效率提升原因
- 跳过逐元素遍历和类型转换,直接批量操作内存,时间复杂度从O(n*m)降至接近O(1)的内存拷贝/映射。
- numpy的
frombuffer和as_array都是极低开销的操作,远快于fromiter或手动遍历。
注意事项
- 确保C#数组内存处于固定(pinned)状态,避免GC移动内存导致指针失效;使用pythonnet时
UnsafeAddrOfPinnedArrayElement会自动处理固定逻辑。 - 仅适用于C#多维数组
UInt16[,],交错数组UInt16[][]内存不连续,无法用此方法。
内容的提问来源于stack exchange,提问作者zeitoun
相关产品推荐
相关产品推荐

