-
2021-02-06 14:36:52
我正在使用一个非托管库,它可以生成灰度图像(大约100x200像素,或多或少).图像包含在结构中,在C中如下所示:
typedef struct abs_image {
ABS_DWORD Width;
ABS_DWORD Height;
ABS_DWORD ColorCount;
ABS_DWORD HorizontalDPI;
ABS_DWORD VerticalDPI;
ABS_BYTE ImageData[ABS_VARLEN];
} ABS_IMAGE
typedef unsigned int ABS_DWORD;
typedef unsigned char ABS_BYTE;
在这里我的C#包装器结构:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct ABS_IMAGE {
public uint Width;
public uint Height;
public uint ColorCount;
public uint HorizontalDPI;
public uint VerticalDPI;
public IntPtr ImageData;
}
抓取图像并对ABS_IMAGE结构进行marshallign 工作就好了.在以前的版本中,我尝试使用固定长度的字节数组用于ImageData,有时会崩溃.我想这发生了,因为图像尺寸没有修复.现在我尝试在以后读取图像字节数组,之后我可以计算实际的数组长度.这里有相关代码:
ABS_Type_Defs.ABS_IMAGE img =
(ABS_Type_Defs.ABS_IMAGE)Marshal.PtrToStructure(
pImage,
typeof(ABS_Type_Defs.ABS_IMAGE));
int length = ((int)img.Height - 1) * ((int)img.Width - 1);
byte[] data = new byte[length];
Marshal.Copy(img.ImageData, data, 0, length);
现在我的问题:每次我想执行Marshal.Copy来读取图像字节,我得到一个AccessViolationException.
有没有人有想法?
更多相关内容 -
Marshal.copy 崩溃问题
2021-03-22 11:20:35在执行Marshal.Copy的时候,崩溃,使用try catch完全捕获不到,进程直接退出了。代码如下: <code>public static bool ImageMirrorCv(ref int[] image, int width, int height, int ... -
测试Bitmap和Marshal.Copy
2021-08-13 11:14:41#region 测试Bitmap和Marshal.Copy public static void TestBitmapAndMarshalCopy() { //测试Bitmap和Marshal.Copy Bitmap bitmap1 = new Bitmap("./123456.jpg"); Rectangle rectangle = new Rectangle(0, 0, ...#region 测试Bitmap和Marshal.Copy public static void TestBitmapAndMarshalCopy() { //测试Bitmap和Marshal.Copy Bitmap bitmap1 = new Bitmap("./123456.jpg"); Rectangle rectangle = new Rectangle(0, 0, bitmap1.Width, bitmap1.Height); //锁定bitmap到系统内存 System.Drawing.Imaging.BitmapData bitmapData = bitmap1.LockBits(rectangle, System.Drawing.Imaging.ImageLockMode.ReadWrite, bitmap1.PixelFormat); //BitmapData 指定 Bitmap 的特性,如大小、像素格式、像素数据在内存中的起始地址以及每个扫描行的长度(步幅)。 var pixel = bitmapData.PixelFormat; //Bitmap 的特性 宽度 var Width = bitmapData.Width;//Bitmap 的特性 宽度 var Height = bitmapData.Height; //Bitmap 的特性 高度 var firstStartAddress = bitmapData.Scan0;//像素数据在内存中的起始地址 var Stride = bitmapData.Stride;//像素数据在内存中的每个扫描行的长度(步幅) var leength = Math.Abs(bitmapData.Stride) * bitmapData.Height; byte[] bts = new byte[leength]; // 将数据从非托管内存指针复制到托管 8 位无符号整数数组 System.Runtime.InteropServices.Marshal.Copy(firstStartAddress, bts, 0, bts.Length); //使rgb图片变红色 for (int i = 2; i < bts.Length; i += 3) { bts[i] = 255; } //将数据从一维托管 8 位无符号整数数组复制到非托管内存指针。 System.Runtime.InteropServices.Marshal.Copy(bts, 0, firstStartAddress, bts.Length); bitmap1.UnlockBits(bitmapData); bitmap1.Save("./123456new.jpg", System.Drawing.Imaging.ImageFormat.Jpeg); bitmap1.Dispose(); //测试托管内存到非托管内存 string a = "123456"; IntPtr dd = System.Runtime.InteropServices.Marshal.AllocHGlobal(10); char[] chars = a.ToCharArray(); // 将数据从一维托管字符数组复制到非托管内存指针。 System.Runtime.InteropServices.Marshal.Copy(chars, 0, dd, chars.Length); //修改 // char[] chars1 = new char[chars.Length]; //将数据从非托管内存指针复制到托管字符数组。 System.Runtime.InteropServices.Marshal.Copy(dd, chars1, 0, chars.Length); System.Runtime.InteropServices.Marshal.FreeHGlobal(dd); } #endregion
-
C# Marshal.Copy实现非托管指针和数组之间的转换
2019-11-03 23:47:54C# Marshal.Copy实现非托管指针和数组之间的转换 挑战 VectorFileIO套件里面 读写文件是 IntPtr类型的指针操作。 原始数据是Int32数组(Int[采样点,通道]),要写入文件。读出文件要转换成反映的物理变量是采集的...C# Marshal.Copy实现非托管指针和数组之间的转换
挑战
VectorFileIO套件里面 读写文件是 IntPtr类型的指针操作。 原始数据是Int32数组(Int[采样点,通道]),要写入文件。读出文件要转换成反映的物理变量是采集的double波形 (double[通道,采样点])。
写文件
//初始化缓存指针对应的非托管内存 IntPtr IntPtr变量 = Marshal.AllocHGlobal(缓存Byte长度); 采集循环 { //讲采集得到的Int一维数组拷贝到缓存 Marshal.Copy(采集一维数组, 0, IntPtr变量, 数组sample长度); //将缓存写入矢量文件 vectorFile.Write(IntPtr变量, 缓存Byte长度); } //释放缓存 Marshal.FreeHGlobal(IntPtr变量); //关闭文件 vectorFile.Close();
读文件
//初始化缓存指针对应的非托管内存 IntPtr IntPtr变量 = Marshal.AllocHGlobal(缓存Byte长度); 读文件循环 { //矢量文件读入缓存 vectorFile.read(IntPtr变量, 缓存Byte长度); //缓存拷贝入一维数组, 数组长度=缓存Byte长度 /4 (因为4 bytes per int32) Marshal.Copy(IntPtr变量, 一维数组, 0, 数组sample长度); //由Int32 一维数组 转换为2维 double数组使用 } //释放缓存 Marshal.FreeHGlobal(IntPtr变量); //关闭文件 vectorFile.Close();
背景知识
微软C#关于Marshal.Copy的多态解释
https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.marshal.copy?view=netframework-4.8我百度、必应查到的都不太对。所以
-
使用Marshal.Copy把Txt行数据转为Struct类型值
2020-05-31 14:51:00try { Marshal.Copy(bytes, 0, buffer, size); //此处已经完成转换 Employee emp = (Employee)Marshal.PtrToStructure(buffer, typeof(Employee)); //省略很多代码 } catch (Exception ex) { throw new Exception(...添加重要的命名空间:
using System.Runtime.InteropServices;
先建立结构相同(char长度相同)的Struct类型用于转换:
[StructLayout(LayoutKind.Sequential, Pack = 1)] public struct Employee { [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] public char[] EmployeeId; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 30)] public char[] LastName; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 30)] public char[] FirstName; //这里省略很多列 }
数据文本类似下面, 如这三列固定长度(6,30,30):
10001 Nick Yang 10002 Nick2 Yang 10003 Nick3 Yang
代码获取并转换:
/// <summary> /// Get data from interface file /// </summary> public void GetDataFromFile() { try { string path = ConfigurationManager.ConnectionStrings["DataPath"].ConnectionString; if (File.Exists(path)) { string[] rows = File.ReadAllLines(path, Encoding.UTF8); foreach (string row in rows) { byte[] bytes = Encoding.UTF8.GetBytes(row); //以下为重点代码 int size = Marshal.SizeOf(typeof(Employee)); IntPtr buffer = Marshal.AllocHGlobal(size); try { Marshal.Copy(bytes, 0, buffer, size); //此处已经完成转换 Employee emp = (Employee)Marshal.PtrToStructure(buffer, typeof(Employee)); //省略很多代码 } catch (Exception ex) { throw new Exception("Error when Copying bytes from interface to Employee", ex); } finally { Marshal.FreeHGlobal(buffer); } } } else { throw new Exception(string.Format("Error. Can`t not find the interface file at '{0}'", path)); } } catch (Exception ex) { throw new Exception("Error when getting data from interface file.", ex); } }
-
c#中Marshal.Copy()方法的使用
2018-01-28 19:10:23c#中Marshal.Copy()方法的使用 c#中Marshal.Copy方法的使用 Marshal.copy()方法用来在托管对象(数组)和非托管对象(IntPtr)之间进行内容的复制 函数有很多重载,如下所示: Copy(array[]()[], Int32, ... -
一个Marshal.Copy的问题
2016-08-23 16:54:36Marshal.Copy(ptArray, 0, pt, 1); 很显然,TAX_ITEM是一个struct。这个问题的核心是最后一行代码该如何理解呢。我们为此再看下这个Copy函数的MSDN说明: public static void Copy ( IntPtr[] source, ... -
C#调用C++ memcpy实现各种参数类型的内存拷贝 VS marshal.copy的实现 效率对比
2017-06-17 18:13:00C#调用C++ memcpy实现各种参数类型的内存拷贝 VS marshal.copy的实现 效率对比 using System; using System.Runtime.InteropServices; using System.IO; namespace tx { struct ST { public char c1; .... -
Marshal.Copy将指针拷贝给数组
2016-12-22 11:02:00lpStatuss是一个UNITSTATUS*的指针类型实例,并包含SensorDust字段 //定义一个数组类型 ...Marshal.Copy(SensorDust, 0, new IntPtr(lpStatus->SensorDust), SensorDust.Length); 转载于:https... -
C# BitmapData和Marshal.Copy()用法
2015-03-11 17:45:37C# BitmapData和Marshal.Copy()用法 -
Marshal.Copy 之 startIndex 参数的含义
2012-12-23 16:16:00Marshal.Copy 可以将 Array 中的数据拷贝给 IntPtr 所指向的地址,也可以将 IntPtr 地址中的内容拷贝给 Array。 不管是从哪里拷贝到哪里,其中都有一个参数 startIndex。那么这个 startIndex 到底是指 IntPtr 的... -
c#中Marshal.Copy方法的使用
2011-06-03 15:25:00解决的问题:复制数组在内存中的数据到自定义结构中。 类似功能: 在C++中 原型:extern void *memcpy(void *dest, void *src, unsigned int count);... 在c#中Marshal.Copy可以实现类似功能。 需要引 -
Marshal.PtrToStructure与Marshal.StructureToPtr 的使用
2020-08-20 19:53:41//copy the array converted into result, and fill the remaining bytes with 0 for (int i = 0; i ; i++) result[i] = ((i < strBytes.Length) ? strBytes[i] : _fillChar); return result; } //show the person ... -
测试复制数组:Array.Copy与Buffer.BlockCopy的性能(运行时间)
2020-10-22 16:39:581.Array.Copy(Array sourceArray, int sourceIndex, Array destinationArray, int destinationIndex, int length) 2.Buffer.BlockCopy(Array src, int srcOffset, Array dst, int dstOffset, int count) 下面... -
C# Array.Copy()方法与Buffer.BlockCopy()效率对比
2020-03-10 15:25:39i++) { //复制,设置偏移为30 Array.Copy(Bytes, 0, arr, 30, Len); } stopwatch.Stop(); Console.WriteLine($"ArryCopy:{stopwatch.ElapsedMilliseconds}"); } public void BlockBuffer() { byte[] arr = new ... -
异常:System.Runtime.InteropServices.Marshal.GetTypeFromCLSID(System.Guid)
2016-10-27 22:30:00异常:System.Runtime.InteropServices.Marshal.GetTypeFromCLSID(System.Guid) 原因:该引用所需.NET Framework版本为4.5.1,而服务器上的.NET Framework版本低于4.5.1。 解决方法:将项目的.NET Framework版本降... -
C#指针操作Marshal实例
2021-04-29 17:33:19static void Main(string[] args) { byte[] a = new byte[]{0,0,0,0}; byte[] b = new byte[] {1,... IntPtr pt = Marshal.AllocHGlobal(a.Length); //从source数组的startIndex下标开始复制length个对象到ptr; ... -
C#数据结构-Array.Copy和Buffer.BlockCopy详解
2018-03-28 16:53:30通过对C#文档中Array.Copy()和Buffer.BlockCopy()两个方法的整理,深刻理解其运行原理及实现方式。在理解了Array.Copy()之后,从而对List<T>的拷贝、插入、删除操作实现,有一个更深入的理解。 一、Array.... -
C# 指针 内存控制 Marshal 内存数据存储原理
2020-07-22 12:16:33//将source变量的数组数据拷贝到address内存块中 Marshal.Copy(source: source, startIndex: 0, //从source的第一个item开始 length: 3, //选择source的3个item destination: address); //选择存储的目标 (会写到... -
Marshal.Copy 是不能从非托管指针的偏移位置复制数据的,要重新计算非托管指针的值...
2011-11-28 17:11:00Marshal.Copy 是不能从非托管指针的偏移位置复制数据的,要重新计算非托管指针的值 Marshal.Copy 是不能从非托管指针的偏移位置复制数据的,要重新计算非托管指针的值 /// /// 读数据 /// /// 数据 /// ... -
MarShal.Copy
2012-03-12 10:58:35为什么用MarShal.Copy时,我传Byte[]类型可以,用float[]就不可以了呢? 附代码: int iWidth = col; int iHeight = row; Bitmap Result = new Bitmap(iWidth, iHeight, System.Drawing.Imaging.Pixel...