DLL文件是C++的。原来在c++下面的定义分别是
LONG NET_DVR_RealPlay_V30(
  LONG                     lUserID,
  LPNET_DVR_CLIENTINFO     lpClientInfo,
  fRealDataCallBack_V30    cbRealDataCallBack,
  void                     *pUser,
  BOOL                     bBlocked
);
typedef void(CALLBACK *fRealDataCallBack_V30)(
  LONG      lRealHandle,//当前的预览句柄 
  DWORD     dwDataType,//数据类型 
  BYTE      *pBuffer,//存放数据的缓冲区指针 
  DWORD     dwBufSize,//缓冲区大小 
  void      *pUser
);BOOL PlayM4_OpenStream(LONG nPort,PBYTE pFileHeadBuf,DWORD nSize,DWORD nBufPoolSize);
   说明:打开流接口(类似打开文件);
   输入参数:pFileHeadBuf用户从回调中得到的文件头数据。nSize 文件头长度。
   nBufPoolSize 设置播放器中存放数据流的缓冲区大小。
BOOL PlayM4_InputData(LONG nPort,PBYTE pBuf,DWORD nSize);
   说明:输入从卡上得到的流数据;打开流之后才能输入数据。
   输入参数:pBuf 缓冲区地址;
   nSize缓冲区大小
    返回值:TURE,表示已经输入数据。FALSE 表示失败,数据没有输入;我在c#里面写成如下:
[DllImport("HCNetSDK.dll")]
public static extern Int32 NET_DVR_RealPlay_V30(Int32 lUserID, ref NET_DVR_CLIENTINFO lpClientInfo, fRealDataCallBack_V30 cbRealDataCallBack, IntPtr pUser, bool bBlocked); public delegate void fRealDataCallBack_V30(Int32 lRealHandle, UInt32 dwDataType, [MarshalAs(UnmanagedType.LPArray)] byte[] pBuffer, UInt32 dwBufSize, System.IntPtr pUser);   [DllImport("PlayCtrl.dll", EntryPoint = "PlayM4_OpenStream", CharSet = CharSet.Ansi)]
    public static extern bool PlayM4_OpenStream(Int32 nPort, byte[] pFileHeadBuf, UInt32 nSize, UInt32 nBufPoolSize);
  [DllImport("PlayCtrl.dll", EntryPoint = "PlayM4_SetStreamOpenMode", CharSet = CharSet.Ansi)]
        public static extern bool PlayM4_InputData(Int32 nPort, byte[] pBuf, System.UInt32 nBufSize);
   现在的问题是fRealDataCallBack_V30里面的BYTE *pBuffer,是存放数据的缓冲区指针
PlayM4_OpenStream里面的PBYTE pFileHeadBuf是存放数据的缓冲区指针 
PlayM4_InputData里面的PBYTE pBuf是缓冲区地址,
,而c#里面又没有指针,现用byte[] pBuffer,byte[] pFileHeadBuf,byte[] pBuf代替,但是这样一来,字节数组的长度是固定的只有1位,无法接收更长的数据,而实际缓冲区每次长度都不一样,无法固定,如果使用[MarshalAs(UnmanagedType.LPArray,SizeConst=999999)] byte[],指定大小,这样会提示未处理 System.AccessViolationException
Message: 尝试读取或写入受保护的内存。这通常指示其他内存已损坏。我该如何定义?请高手指教

解决方案 »

  1.   

    具体代码如下:
    //回调函数
      public static void frealdatacallback_v3(Int32 lRealHandle, UInt32 dwDataType,  ref  byte [] pBuffer, UInt32 dwBufSize, IntPtr pUser)
           {
                switch (dwDataType)
                {
                    // #define NET_DVR_SYSHEAD  1 //系统头数据
                    //  #define NET_DVR_STREAMDATA  2 //视频流数据(包括复合流和音视频分开的视频流数据)
                    //  #define NET_DVR_AUDIOSTREAMDATA 3//音频流数据
                    //  #define NET_DVR_STD_VIDEODATA 4//标准视频流数据
                    //  #define NET_DVR_STD_AUDIODATA 5//标准音频流数据                case 1: //系统头
                        {
                            UInt32 s;
                   if (!PlayM4_GetPort(ref lPort))//打开通道
                       {MessageBox.Show("MP4获得通道失败" + PlayM4_GetLastError(lPort).ToString());                   }                        if (dwBufSize > 0)//缓冲区数据长度大于0
                            {
                         //set as stream mode, real-time stream under preview实时模式
                if (!PlayM4_SetStreamOpenMode(lPort, STREAME_REALTIME))//设置解码方式                            {
          MessageBox.Show("设置流播放的模式失败"+PlayM4_GetLastError(lPort).ToString());
                                }
                                //start player   pBuffer 打开码流
                   if (!PlayM4_OpenStream(lPort, ref pBuffer, dwBufSize, 1024*1024))
                   {             
    -----------------------在这里出错,字节数组长度不一样---------------------------
                      
                   MessageBox.Show("打开流接口失败"+PlayM4_GetLastError(lPort).ToString());
                      break;
                    }                                      
      //start play, set play window                        if (!PlayM4_Play(lPort, hhw))
                           {
                     MessageBox.Show("播放失败" + PlayM4_GetLastError(lPort).ToString());
                                    break;
                            }
                               
                            }
                            break;
                        }                case 2://视频流数据
                        {
                        if (dwBufSize > 0 && lPort != -1)
                       {      
                      if (!PlayM4_InputData(lPort,  pBuffer, dwBufSize))
                      { 
                       MessageBox.Show("输入数据"+PlayM4_GetLastError(lPort).ToString());
    -----------------------在这里出错,提示代码为1:输入参数错误---------------------------
                                }
                              else 
                                {
                                   
                                }                               ///PlayM4_Stop(lPort);
                               //PlayM4_CloseStream(lPort);                        }
                           
                            break;
                           
                        }
                    case 4:
                    case 5:
          
                    default:
                        break;            }
            }
      

  2.   

    帮你改改:
    [DllImport("HCNetSDK.dll")]
    public static extern Int32 NET_DVR_RealPlay_V30(Int32 lUserID, ref NET_DVR_CLIENTINFO lpClientInfo, fRealDataCallBack_V30 cbRealDataCallBack, IntPtr pUser, 
    [MarshalAs(UnmanagedType.Bool)]bool bBlocked); public delegate void fRealDataCallBack_V30(Int32 lRealHandle, UInt32 dwDataType, [In,Out] byte[] pBuffer, UInt32 dwBufSize, IntPtr pUser);  [DllImport("PlayCtrl.dll", EntryPoint = "PlayM4_OpenStream", CharSet = CharSet.Ansi)]
      [retrun:MarshalAs(UnmanagedType.Bool)]
      public static extern bool PlayM4_OpenStream(Int32 nPort, byte[] pFileHeadBuf, UInt32 nSize, UInt32 nBufPoolSize);
      [DllImport("PlayCtrl.dll", EntryPoint = "PlayM4_SetStreamOpenMode", CharSet = CharSet.Ansi)]
      [retrun:MarshalAs(UnmanagedType.Bool)]
      public static extern bool PlayM4_InputData(Int32 nPort, byte[] pBuf, UInt32 nBufSize);
      

  3.   

    我试一下。
    能不能用下面方法进行转换。
    将非托管函数指针转换为委托。public static Delegate GetDelegateForFunctionPointer(IntPtr ptr,Type t)将委托转换为可从非托管代码调用的函数指针。
    public static IntPtr GetFunctionPointerForDelegate(Delegate d)
      

  4.   

    #2楼的
    你定义的public delegate void fRealDataCallBack_V30(Int32 lRealHandle, UInt32 dwDataType, [In,Out] byte[] pBuffer, UInt32 dwBufSize, IntPtr pUser);
    [In,Out] byte[] pBuffer,为什么不直接用 ref byte[] pBuffer
      

  5.   

    两种本质是一样的,语法形式不一样!
    ref更多直接对应单个类型的成员,而数组用[In,Out],会更直观,
    这点在MSDN上说明
      

  6.   

    不行,运行到 if (!PlayM4_OpenStream(lPort,   pBuffer, dwBufSize, 1024*1024))这里就出错了。我中断中看到的是pBuffer[0]=52,dwBufSize=40,
      

  7.   

    我找到问题了。定义成intprt类型就可以了。但是又出现新的问题,在回调函数fRealDataCallBack_V30里面再次调用DecCBFun这个回调函数时出错:DecCBFun::Invoke”类型的已垃圾回收委托进行了回调。这可能会导致应用程序崩溃、损坏和数据丢失。向非托管代码传递委托时,托管应用程序必须让这些委托保持活动状态,直到确信不会再次调用它们。