请教大家 C#调用C++ DLL出现的疑难杂症

wuyiming8 2012-01-16 04:04:56
请教大家一个问题,现在有个C++ PCIDLL.dll文件,在C#中调用 dll,老是出现错误如下:System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

请问C#代码哪里有误,我试了几天都没解决, 烦请高手指点,谢谢!

C++ Code:

结构体:------------------------------------------
typedef struct _DEV_CTRL_PARAM { intScanType;
intSelChannel[12];
intmParamType;
int*mEtalonPeakNum;
float*p_EtalonPeakVal;
}DEV_CTRL_PARAM,*PDEV_CTRL_PARAM;

externBOOL _stdcallPci_InitDevice(int mDev,PDEV_CTRL_PARAM pParam);

调用: --------------------------------------------
int mEtalonPeakNum = 0;
floatEtalonPeakVal[400];
DEV_CTRL_PARAM mParam;
int temptype[7] ={6,5,4,3,2,1,0};
mParam.ScanType=3;
mParam.mParamType = 0;
mParam.mEtalonPeakNum = &mEtalonPeakNum;
mParam.p_EtalonPeakVal = EtalonPeakVal;
mParam.SelChannel[0] = 1;
mParam.SelChannel[1] = 1;
mParam.SelChannel[2] = 1;
mParam.SelChannel[3] = 1;
mParam.SelChannel[4] = 1;
mParam.SelChannel[5] = 1;
mParam.SelChannel[6] = 1;
mParam.SelChannel[7] = 1;
mParam.SelChannel[8] = 1;
mParam.SelChannel[9] = 1;
mParam.SelChannel[10] = 0;
mParam.SelChannel[11] = 0;

Pci_InitDevice(0,&mParam);
----------------------------------------------------------------------------------

C# Code:
结构体:--------------
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct DEV_CTRL_PARAM
{
public int ScanType;
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.I4, SizeConst = 12)]
public int[] SelChannel;
public int mParamType;
public IntPtr mEtalonPeakNum;
public IntPtr p_EtalonPeakVal;
}

[DllImport("PCIDLL.dll")]
public static extern bool Pci_InitDevice(int mDev, ref DEV_CTRL_PARAM pParam);

调用:------------------------
DEV_CTRL_PARAM mParam;

mParam.SelChannel = new int[12];
int mEtalonPeakNum = 0;
float[] EtalonPeakVal = new float[400];
int[] temptype = new int[7] { 6, 5, 4, 3, 2, 1, 0 };
mParam.ScanType = 3;
mParam.mParamType = 0;

mParam.mEtalonPeakNum = (IntPtr)mEtalonPeakNum;
mParam.p_EtalonPeakVal = Marshal.UnsafeAddrOfPinnedArrayElement(EtalonPeakVal, 0);


mParam.SelChannel[0] = 1;
mParam.SelChannel[1] = 1;
mParam.SelChannel[2] = 1;
mParam.SelChannel[3] = 1;
mParam.SelChannel[4] = 1;
mParam.SelChannel[5] = 1;
mParam.SelChannel[6] = 1;
mParam.SelChannel[7] = 1;
mParam.SelChannel[8] = 1;
mParam.SelChannel[9] = 1;
mParam.SelChannel[10] = 0;
mParam.SelChannel[11] = 0;

Pci_InitDevice(0, ref mParam);
...全文
85 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
Ricechen1989 2012-01-16
  • 打赏
  • 举报
回复
C#中int,好像是32位的,你把那句改成 [DllImport("PCIDLL.dll")]
public static extern bool Pci_InitDevice(int32 mDev, ref DEV_CTRL_PARAM pParam);我也遇到这个问题的,搞了半天才弄出来的

knf 2012-01-16
  • 打赏
  • 举报
回复
不能直接传递数组,可以用指针,或者用下面的办法。
传递数组给C++DLL时,
传递C#数组的第一个元素和数组长度,并且用ref。
由于数组在内存中是连续存放的,DLL获取到第一个元素的ref和数组长度,自己用代码设定一下数组长度。
Dll: fun(int[] array,int arrayLength)
声明:[DllImport("xxx.dll", CallingConvention = CallingConvention.StdCall)]
调用:fun(ref array[0],array.Length)

我前几天用这种方法传递数组给delphi的DLL成功,C++应该也一样吧。
Saleayas 2012-01-16
  • 打赏
  • 举报
回复

mParam.mEtalonPeakNum = (IntPtr)mEtalonPeakNum;
mParam.p_EtalonPeakVal = Marshal.UnsafeAddrOfPinnedArrayElement(EtalonPeakVal, 0);


不是这样的,需要使用
StructToPtr 或者 PtrToStruct 函数。
如果是数组,那么需要分配本地内存。
AllocCoTaskMem
oneleafpz 2012-01-16
  • 打赏
  • 举报
回复
两个办法
1,SelChannel用fixed关键字声明
2,不用ref,直接使用指针
至于行不行,我不知道
你试试

110,536

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧