服务周到的上海网站建设公/淘宝seo 优化软件 - 文章中心
服务周到的上海网站建设公/淘宝seo 优化软件
2024-12-28

C#调用 非托管C++ dll 传入Stringbuilder、ref string 、 ref char 等都报错,如mscorlib.dll 异常、其他信息: 尝试读取或写入受保护的内存。这通常指示其他内存已损坏 等等,后来发现是dll 生成后一直没更新,放错位置了。。。 = =||
不过也学习了一下编译器及类型相关的知识,整理如下
1、 cl.exe /Gz 参数指定编译为 __stdcall 调用方式,默认为 __cdecl

服务周到的上海网站建设公/淘宝seo 优化软件

2、C#中的char是两个字节
http://msdn.microsoft.com/zh-cn/library/x9h8tsay(v=vs.80).aspx
类型 范围 大小 .NET framework 类型
char
U+0000 到 U+ffff
16 位 Unicode 字符
System.Char

类型

范围

大小

.NET framework 类型

byte

0 到 255

无符号 8 位整数

System.Byte

3、C++ dll 类型与 C#类型对应关系

参考

本以为这篇搜集整理的代码会是很不错的文章,花了一天时间,搜索到最后居然出来一篇叫做”C# 与 C++ 数据类型对照表”的文章.几乎囊括掉和大部分的数据了,太打击我了. 本文中有部分的数据没有测试.也有一些不错的是看了上百篇网文对比整理得来的.希望有帮助.

 

4、C#调用C++dll的几种传参方式
refer: http://www.camnpr.com/archives/293.html
C#调用非托管DLL中的API

LONG APIENTRY devwdm_GetImageBuffer(BYTE *pImageMem);
函数功能: 采集一帧RGB24图像到内存
pImageMem: 图像缓冲区指针

C#调用

C# code

[Dllimport(“devwdm.dll”)]
public static extern int devwdm_GetImageBuffer(IntPtr pImageMem);

于是报错:尝试读取或写入受保护的内存。这通常指示其他内存已损坏。
求助于大家,根据大家的意见,把API中的 BYTE* 转换到C#中,分别用 byte[] 、IntPtr 、ref byte[]、 …甚至用unsafe了,可是还是报错,有人说内存不够大,于是我非配了很大的内存,扔报错…

万般无奈,去C++的示例程序中看,示例程序中调用该函数没有任何问题。
pImageMem是用来存放图象数据的缓冲区 字节数组(长*宽*3)
lpsz是文件名(用于保存图象) 字符数组(Unicode/ANSI)
devwdm_GetImageBuffer(pImageMem); 对字节数组赋值
CT_SaveBmp(lpsz,pImageMem,m_strWideth,m_strHeight,0);以BMP格式保存
CT_SaveJpeg(lpsz,pImageMem,m_strWideth,m_strHeight,0);以JPG格式保存

以C#重写上述功能,要注意的几点:
1,获取正确的m_strWideth和m_strHeight ,据此申请内存块:
IntPtr ptrImage = Marshal.AllocHGlobal(m_strWideth*m_strHeight*3);
2,构建文件名,szFile是用户输入的字符串?
string filename = “XXX”;
IntPtr ptrFileName = Marshal.AllocHGlobal(filename.Length+1);
Marshal.Copy(s.ToCharArray(), 0, ptrFileName, s.Length);
3,获取图像数据:
devwdm_GetImageBuffer(ptrImage);
4,保存BMP
CT_SaveBmp(ptrFileName,ptrImage,m_strWideth,m_strHeight,0);
托管数组向非托管代码封送:

试试这样:
如果有byte[] data字节数组,如下调用:
devwdm_GetImageBuffer([In, MarshalAs( UnmanagedType.LPArray)] data);

或者手工转换成非托管数组:
IntPtr ptr = Marshal.AllocHGlobal(data.Length);//申请非托管内存块(与data大小一样)
Marshal.Copy(data,0,ptr,data.Length);//将托管数据复制到非托管数据
devwdm_GetImageBuffer(ptr);//直接以非托管内存块地址为参数
Marshal.FreeHGlobal(ptr);//处理完后记得释放内存

发生错误的原因是devwdm_GetImageBuffer的参数的指针没有正确指到数据内存块,当指向受保护的系统内存块并且发生读写时,就会提示上述错误,与内存大小一点关系没有
byte[] UUID2 = new byte[37];
UUID2 = System.Text.Encoding.ASCII.GetBytes(Request[“uid”].Trim());
char& 和 int& ,&是取地址,在c#中byte型的数组就是表示地址的,所以,对应的类型就是byte,如果是指定长度的char的话,要用byte[] ,一定要指定长度,只可大不可小。具体咨询本站站长。

  I   II   III   IV