关闭

c# 调用 C++ dll 传入传出 字符串

发表于:2013-7-05 10:02

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:yatusiter    来源:51Testing软件测试网采编

  C#调用 非托管C++ dll 传入Stringbuilder、ref string 、 ref char 等都报错,如mscorlib.dll 异常、其他信息: 尝试读取或写入受保护的内存。这通常指示其他内存已损坏 等等

  后来看到文章提到byte,想起来之前调用没有问题是用的byte,C#中的char是两个字节,用byte能证明标识内存地址

  http://msdn.microsoft.com/zh-cn/library/x9h8tsay(v=vs.80).aspx


  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[]  ,一定要指定长度,只可大不可小。具体咨询本站站长。

《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号