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: 尝试读取或写入受保护的内存。这通常指示其他内存已损坏。我该如何定义?请高手指教
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: 尝试读取或写入受保护的内存。这通常指示其他内存已损坏。我该如何定义?请高手指教
//回调函数
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; }
}
[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);
能不能用下面方法进行转换。
将非托管函数指针转换为委托。public static Delegate GetDelegateForFunctionPointer(IntPtr ptr,Type t)将委托转换为可从非托管代码调用的函数指针。
public static IntPtr GetFunctionPointerForDelegate(Delegate d)
你定义的public delegate void fRealDataCallBack_V30(Int32 lRealHandle, UInt32 dwDataType, [In,Out] byte[] pBuffer, UInt32 dwBufSize, IntPtr pUser);
[In,Out] byte[] pBuffer,为什么不直接用 ref byte[] pBuffer
ref更多直接对应单个类型的成员,而数组用[In,Out],会更直观,
这点在MSDN上说明