原型:
long STDCALL IPCNET_StartRealData(long lLoginID,S_REALDATA_INFO *pRealDataInfo,CBRealData fRealData,Void *pUserData = NULL)
参数说明:
lLoginID long 登陆的ID,IPCNET_Login的返回值
sRealDataInfo S_REALDATA_INFO * 实时数据流的参数结构体
fRealData CBRealData 码流数据回调函数,参见CBRealData回调函数说明
pUserData void * 用户自定义的数据,回调函数原值返回
实时数据流的参数结构体:
原型:
typedef struct tagRealDataInfo
{
unsigned long lChannel; /**< 通道号,从0开始 */
unsigned long lStreamMode; /**< 码流类型,0-主码流,1-子码流 */
E_ENCODE_TYPE eEncodeType; /**< 编码类型 */
}S_REALDATA_INFO;
编码类型枚举
原型:
typedef enum tagEncodeType
{
ENCODE_MPEG4 = 1, /**< MPEG4编码 */
ENCODE_H264, /**< H264编码 */
ENCODE_H264_Hi3510, /**< H264 3510编码 */
ENCODE_MJPEG, /**< MJPEG编码,暂无用 */
} E_ENCODE_TYPE;
回调实时流的数据类型
原型:
typedef enum tagRealDataType
{
REALDATA_HEAD, /**< 实时流的头数据 */
REALDATA_VIDEO, /**< 实时视频流数据(包括复合流和音视频分开的视频流数据) */
REALDATA_AUDIO, /**< 实时音频流数据 */
} E_REALDATA_TYPE;
回调函数说明
原型:
typedef void (CALLBACK *CBRealData)(long lRealHandle, E_REALDATA_TYPE eDataType, unsigned char *pBuffer, unsigned long lBufSize,void *pUserData)
参数说明:
lRealHandle long 当前的实时数据的句柄
eDataType E_REALDATA_TYPE 回调的数据类型
pBuffer unsigned char * 存放数据的缓冲区指针
lBufSize unsigned long 存放数据的缓冲区大小
pUserData void* 用户数据,调用IPCNET_StartRealData时用户输入的值
--------------------------------------------------------
以上是c++的接口说明文档,定义的c#代码如下,
public struct S_REALDATA_INFO
{
public uint lChannel; /**< 通道号,从0开始 */
public uint lStreamMode; /**< 码流类型,0-主码流,1-子码流 */
public E_ENCODE_TYPE eEncodeType; /**< 编码类型 */
}
public enum E_ENCODE_TYPE
{
ENCODE_MPEG4 = 1, /**< MPEG4编码 */
ENCODE_H264, /**< H264编码 */
ENCODE_H264_Hi3510, /**< H264 3510编码 */
ENCODE_MJPEG, /**< MJPEG编码,暂无用 */
};
public enum E_REALDATA_TYPE
{
REALDATA_HEAD, /**< 实时流的头数据 */
REALDATA_VIDEO, /**< 实时视频流数据(包括复合流和音视频分开的视频流数据) */
REALDATA_AUDIO, /**< 实时音频流数据 */
} ;
public delegate void CBRealData(int lRealHandle, E_REALDATA_TYPE eDataType, IntPtr pBuffer, uint lBufSize, byte[] pUserData);
[DllImport("IPCSDK_Net.dll", CallingConvention = CallingConvention.StdCall)]
private static extern int IPCNET_StartRealData(int lLoginID, ref S_REALDATA_INFO sRealDataInfo, CBRealData fRealData, byte[] pUserData = null);
//登陆设备成功后通过回调函数返回实时数据
private void btnLogin_Click(object sender, EventArgs e)
{
bool flag = IPCNET_Init();
string ip = "192.168.1.110";
string name = "admin";
string psw= "admin";
int lLoginID = IPCNET_Login(ip, 90, name, psw);
CBRealData callback = new CBRealData(getCallBack);
S_REALDATA_INFO info = new S_REALDATA_INFO { lChannel = 1, lStreamMode = 0, eEncodeType = E_ENCODE_TYPE.ENCODE_H264 };
int jubing = IPCNET_StartRealData(lLoginID, ref info, callback);
}
//回调函数
public static void getCallBack(int lRealHandle, E_REALDATA_TYPE eDataType, IntPtr pBuffer, uint lBufSize, byte[] pUserData)
{
MessageBox.Show("回调成功");
return;
}
现在的问题是调用C++的IPCNET_StartRealData函数已成功,但是C#定义的回调函数并没有执行,我试过将委托参数pBuffe定义为IntPtr,string,stringbuilder,byte[],ref byte,unsafe char*回调函数getCallBack还是没有执行,求大神解答。
20 个解决方案
#1
c# C函数callback 估计没戏.
#2
先确定是没有被呼叫,还是呼叫回调函数错误。
前者是逻辑的问题,后者是语法的问题。
前者是逻辑的问题,后者是语法的问题。
#3
调试发现定义的回调函数根本没有被调用,不知道是不是定义委托不对
#4
网上有成功例子,但我没成功
#5
首先,C# 肯定是可以使用回调的。
你调试 C++ 代码看看到底是因为什么没有呼叫 回调函数。看看是不是逻辑有问题。
你调试 C++ 代码看看到底是因为什么没有呼叫 回调函数。看看是不是逻辑有问题。
#6
我晕,还真能生成回调来
CBRealData callback = new CBRealData(getCallBack);
//看看是不是少了这步,回调要给函数指针....
IntPtr pRealData = Marshal.GetFunctionPointerForDelegate(callback ); //获取函数指针
int jubing = IPCNET_StartRealData(lLoginID, ref info,pRealData);
CBRealData callback = new CBRealData(getCallBack);
//看看是不是少了这步,回调要给函数指针....
IntPtr pRealData = Marshal.GetFunctionPointerForDelegate(callback ); //获取函数指针
int jubing = IPCNET_StartRealData(lLoginID, ref info,pRealData);
#7
unsigned char * 可以用[MarshalAs(UnmanagedType.LPArray)]byte[],当然,用IntPtr也可以
void * 俗称万能指针,用IntPtr
void * 俗称万能指针,用IntPtr
#8
看不到C++源代码,逻辑没有问题,别人用C++写的Demo是可以正常回调的
#9
加了这句IntPtr pRealData = Marshal.GetFunctionPointerForDelegate(callback ); //获取函数指针
也不行
#10
你把 MessageBox.Show("回调成功"); 改成 MessageBoxA(0,"test","test",1);测试下
回调里调用.net里的方法,总觉得有问题。
#11
unsigned char * 可以用[MarshalAs(UnmanagedType.LPArray)]byte[],当然,用IntPtr也可以
void * 俗称万能指针,用IntPtr
试过了不管用
#12
我晕,还真能生成回调来
CBRealData callback = new CBRealData(getCallBack);
//看看是不是少了这步,回调要给函数指针....
IntPtr pRealData = Marshal.GetFunctionPointerForDelegate(callback ); //获取函数指针
int jubing = IPCNET_StartRealData(lLoginID, ref info,pRealData);
加了这句IntPtr pRealData = Marshal.GetFunctionPointerForDelegate(callback ); //获取函数指针
也不行
你把 MessageBox.Show("回调成功"); 改成 MessageBoxA(0,"test","test",1);测试下
回调里调用.net里的方法,总觉得有问题。
c#winform没有MessageBoxA,别人用C++是可以回调的,代码如下:
void CALLBACK RealData(long lRealHandle,
E_REALDATA_TYPE eDataType,
unsigned char *pBuffer,
unsigned long lBufSize,
void *pUserData)
{
CPreviewDlg *pDlg = (CPreviewDlg*)pUserData;
switch (eDataType)
{
case REALDATA_HEAD:
pDlg->m_lPlayHandle = HDVPLAY_OpenStream(pBuffer,lBufSize);
if(pDlg->m_lPlayHandle < 0)
{
TRACE("HDVPLAY_OpenStream\n");
return;
}
if(!HDVPLAY_Play(pDlg->m_lPlayHandle,pDlg->GetSafeHwnd(),g_struLocalParam.bCloseSound))
{
TRACE("HDVPLAY_Play\n");
return;
}
HDVPLAY_SetDrawFunCallBack(pDlg->m_lPlayHandle,DrawZoomIn,pDlg);
pDlg->m_bMute = g_struLocalParam.bCloseSound; //TRUE;
g_pMainDlg->ChangePreviewCtrlState();
g_struDeviceInfo[pDlg->m_iDeviceIndex].struChanInfo[pDlg->m_iChanIndex].lRealHandle = 1;
g_pMainDlg->DoChangeChannelImage(pDlg->m_hChanItem, PRE_PLAY);
break;
case REALDATA_VIDEO:
case REALDATA_AUDIO:
if(!HDVPLAY_InputData(pDlg->m_lPlayHandle,pBuffer,lBufSize))
{
TRACE("HDVPLAY_InputData\n");
return;
}
break;
default:
break;
}
return;
}
/*********************************************************
Function: StartPlay
Desc: start play preview
Input: pChanInfo, the imformation of the channel that will be played; hChanItem channel handle
Output:
Return:
**********************************************************/
long CPreviewDlg::StartPlay(PCHANNEL_INFO pChanInfo, HTREEITEM hChanItem)
{
m_iDeviceIndex = pChanInfo->iDeviceIndex;
m_iChanIndex = pChanInfo->iChanIndex;
CString csLog = _T("");
if (g_struDeviceInfo[m_iDeviceIndex].struChanInfo[m_iChanIndex].lRealHandle < 0)
{
S_REALDATA_INFO sRealInfo;
sRealInfo.eEncodeType = g_struDeviceInfo[m_iDeviceIndex].codeType;
sRealInfo.lChannel = m_iChanIndex;
sRealInfo.lStreamMode = m_lStreamMode;
g_struDeviceInfo[m_iDeviceIndex].struChanInfo[m_iChanIndex].lStreamMode = m_lStreamMode;
if (g_struDeviceInfo[m_iDeviceIndex].lLoginID < 0)
{
AfxMessageBox(g_LoadString(IDS_LOGIN_DEVICE));
}
m_lRealDataID = IPCNET_StartRealData(g_struDeviceInfo[m_iDeviceIndex].lLoginID,&sRealInfo, RealData, this);
if (m_lRealDataID >= 0)
{
//以下状态在回调函数中去设置比较好
m_bMute = g_struLocalParam.bCloseSound;
g_pMainDlg->ChangePreviewCtrlState();
g_pMainDlg->AddLog(m_iDeviceIndex, OPERATION_SUCC_T, "IPCNET_StartRealData %s",\
g_struDeviceInfo[m_iDeviceIndex].struChanInfo[m_iChanIndex].cChanName);
m_hChanItem = hChanItem;
g_struDeviceInfo[m_iDeviceIndex].struChanInfo[m_iChanIndex].lRealHandle = 1;
g_pMainDlg->DoChangeChannelImage(m_hChanItem, PRE_PLAY);
}
}
return m_lRealDataID;
}
----------------------------------
我写的C#代码
public delegate void CBRealData(int lRealHandle, E_REALDATA_TYPE eDataType, IntPtr pBuffer, uint lBufSize, IntPtr pUserData);
[DllImport("IPCSDK_Net.dll", CallingConvention = CallingConvention.StdCall)]
public static extern int IPCNET_StartRealData(int lLoginID, ref S_REALDATA_INFO sRealDataInfo, CBRealData fRealData, IntPtr pUserData);
public static void getCallBack(int lRealHandle, E_REALDATA_TYPE eDataType, IntPtr pBuffer, uint lBufSize, IntPtr pUserData)
{
MessageBox.Show("回调成功");
return;
}
private void btnLogin_Click(object sender, EventArgs e)
{
bool init= IPCNET_Init();
bool flag = HDVPLAY_Init();
string ip = "192.168.1.110";
string name = "admin";
string pass = "admin";
int lLoginID = IPCNET_Login(ip, 90, name, pass);
CBRealData callback = new CBRealData(getCallBack);
IntPtr pRealData = Marshal.GetFunctionPointerForDelegate(callback);
S_REALDATA_INFO info = new S_REALDATA_INFO { lChannel = 1, lStreamMode = 0, eEncodeType = E_ENCODE_TYPE.ENCODE_H264 };
int Result = IPCNET_StartRealData(lLoginID, ref info, callback, pRealData);
int error = IPCNET_GetLastError();
}
回调不成功,到底哪里出问题了
#13
你把需要调用.NET的方法用委托传进去试试
#14
你把需要调用.NET的方法用委托传进去试试
我就是用委托传进去的
#15
c# C函数callback 估计没戏.
是一定有戏,用委托即可,我自己就成功过,网上成功的例子就更多了
#16
c# C函数callback 估计没戏.
是一定有戏,用委托即可,我自己就成功过,网上成功的例子就更多了
能不能把你方法放出来看看
#17
大神们出来帮忙啊
#18
把你的 C# 代码用 C++ 调试一下,首先确定你的逻辑没有问题。
如果是 C# 的语法的错误, VS 调试会有信息的。
如果是 C# 的语法的错误, VS 调试会有信息的。
#19
c# C函数callback 估计没戏.
是一定有戏,用委托即可,我自己就成功过,网上成功的例子就更多了
能不能把你方法放出来看看
这个不同的代码具体调用过程会有不同,你可以在工程上点右键属性->调试->启用本机代码调试,直接跟进C++的函数即可,我只有一点可以告诉你,这类情况C#是一定可以成功的
#20
谢谢以上各位,回调已成功,原来是初始化参数时弄错了导致失败
#21
#1
c# C函数callback 估计没戏.
#2
先确定是没有被呼叫,还是呼叫回调函数错误。
前者是逻辑的问题,后者是语法的问题。
前者是逻辑的问题,后者是语法的问题。
#3
先确定是没有被呼叫,还是呼叫回调函数错误。
前者是逻辑的问题,后者是语法的问题。
调试发现定义的回调函数根本没有被调用,不知道是不是定义委托不对
#4
c# C函数callback 估计没戏.
网上有成功例子,但我没成功
#5
首先,C# 肯定是可以使用回调的。
你调试 C++ 代码看看到底是因为什么没有呼叫 回调函数。看看是不是逻辑有问题。
你调试 C++ 代码看看到底是因为什么没有呼叫 回调函数。看看是不是逻辑有问题。
#6
我晕,还真能生成回调来
CBRealData callback = new CBRealData(getCallBack);
//看看是不是少了这步,回调要给函数指针....
IntPtr pRealData = Marshal.GetFunctionPointerForDelegate(callback ); //获取函数指针
int jubing = IPCNET_StartRealData(lLoginID, ref info,pRealData);
CBRealData callback = new CBRealData(getCallBack);
//看看是不是少了这步,回调要给函数指针....
IntPtr pRealData = Marshal.GetFunctionPointerForDelegate(callback ); //获取函数指针
int jubing = IPCNET_StartRealData(lLoginID, ref info,pRealData);
#7
unsigned char * 可以用[MarshalAs(UnmanagedType.LPArray)]byte[],当然,用IntPtr也可以
void * 俗称万能指针,用IntPtr
void * 俗称万能指针,用IntPtr
#8
首先,C# 肯定是可以使用回调的。
你调试 C++ 代码看看到底是因为什么没有呼叫 回调函数。看看是不是逻辑有问题。
看不到C++源代码,逻辑没有问题,别人用C++写的Demo是可以正常回调的
#9
我晕,还真能生成回调来
CBRealData callback = new CBRealData(getCallBack);
//看看是不是少了这步,回调要给函数指针....
IntPtr pRealData = Marshal.GetFunctionPointerForDelegate(callback ); //获取函数指针
int jubing = IPCNET_StartRealData(lLoginID, ref info,pRealData);
加了这句IntPtr pRealData = Marshal.GetFunctionPointerForDelegate(callback ); //获取函数指针
也不行
#10
我晕,还真能生成回调来
CBRealData callback = new CBRealData(getCallBack);
//看看是不是少了这步,回调要给函数指针....
IntPtr pRealData = Marshal.GetFunctionPointerForDelegate(callback ); //获取函数指针
int jubing = IPCNET_StartRealData(lLoginID, ref info,pRealData);
加了这句IntPtr pRealData = Marshal.GetFunctionPointerForDelegate(callback ); //获取函数指针
也不行
你把 MessageBox.Show("回调成功"); 改成 MessageBoxA(0,"test","test",1);测试下
回调里调用.net里的方法,总觉得有问题。
#11
unsigned char * 可以用[MarshalAs(UnmanagedType.LPArray)]byte[],当然,用IntPtr也可以
void * 俗称万能指针,用IntPtr
试过了不管用
#12
我晕,还真能生成回调来
CBRealData callback = new CBRealData(getCallBack);
//看看是不是少了这步,回调要给函数指针....
IntPtr pRealData = Marshal.GetFunctionPointerForDelegate(callback ); //获取函数指针
int jubing = IPCNET_StartRealData(lLoginID, ref info,pRealData);
加了这句IntPtr pRealData = Marshal.GetFunctionPointerForDelegate(callback ); //获取函数指针
也不行
你把 MessageBox.Show("回调成功"); 改成 MessageBoxA(0,"test","test",1);测试下
回调里调用.net里的方法,总觉得有问题。
c#winform没有MessageBoxA,别人用C++是可以回调的,代码如下:
void CALLBACK RealData(long lRealHandle,
E_REALDATA_TYPE eDataType,
unsigned char *pBuffer,
unsigned long lBufSize,
void *pUserData)
{
CPreviewDlg *pDlg = (CPreviewDlg*)pUserData;
switch (eDataType)
{
case REALDATA_HEAD:
pDlg->m_lPlayHandle = HDVPLAY_OpenStream(pBuffer,lBufSize);
if(pDlg->m_lPlayHandle < 0)
{
TRACE("HDVPLAY_OpenStream\n");
return;
}
if(!HDVPLAY_Play(pDlg->m_lPlayHandle,pDlg->GetSafeHwnd(),g_struLocalParam.bCloseSound))
{
TRACE("HDVPLAY_Play\n");
return;
}
HDVPLAY_SetDrawFunCallBack(pDlg->m_lPlayHandle,DrawZoomIn,pDlg);
pDlg->m_bMute = g_struLocalParam.bCloseSound; //TRUE;
g_pMainDlg->ChangePreviewCtrlState();
g_struDeviceInfo[pDlg->m_iDeviceIndex].struChanInfo[pDlg->m_iChanIndex].lRealHandle = 1;
g_pMainDlg->DoChangeChannelImage(pDlg->m_hChanItem, PRE_PLAY);
break;
case REALDATA_VIDEO:
case REALDATA_AUDIO:
if(!HDVPLAY_InputData(pDlg->m_lPlayHandle,pBuffer,lBufSize))
{
TRACE("HDVPLAY_InputData\n");
return;
}
break;
default:
break;
}
return;
}
/*********************************************************
Function: StartPlay
Desc: start play preview
Input: pChanInfo, the imformation of the channel that will be played; hChanItem channel handle
Output:
Return:
**********************************************************/
long CPreviewDlg::StartPlay(PCHANNEL_INFO pChanInfo, HTREEITEM hChanItem)
{
m_iDeviceIndex = pChanInfo->iDeviceIndex;
m_iChanIndex = pChanInfo->iChanIndex;
CString csLog = _T("");
if (g_struDeviceInfo[m_iDeviceIndex].struChanInfo[m_iChanIndex].lRealHandle < 0)
{
S_REALDATA_INFO sRealInfo;
sRealInfo.eEncodeType = g_struDeviceInfo[m_iDeviceIndex].codeType;
sRealInfo.lChannel = m_iChanIndex;
sRealInfo.lStreamMode = m_lStreamMode;
g_struDeviceInfo[m_iDeviceIndex].struChanInfo[m_iChanIndex].lStreamMode = m_lStreamMode;
if (g_struDeviceInfo[m_iDeviceIndex].lLoginID < 0)
{
AfxMessageBox(g_LoadString(IDS_LOGIN_DEVICE));
}
m_lRealDataID = IPCNET_StartRealData(g_struDeviceInfo[m_iDeviceIndex].lLoginID,&sRealInfo, RealData, this);
if (m_lRealDataID >= 0)
{
//以下状态在回调函数中去设置比较好
m_bMute = g_struLocalParam.bCloseSound;
g_pMainDlg->ChangePreviewCtrlState();
g_pMainDlg->AddLog(m_iDeviceIndex, OPERATION_SUCC_T, "IPCNET_StartRealData %s",\
g_struDeviceInfo[m_iDeviceIndex].struChanInfo[m_iChanIndex].cChanName);
m_hChanItem = hChanItem;
g_struDeviceInfo[m_iDeviceIndex].struChanInfo[m_iChanIndex].lRealHandle = 1;
g_pMainDlg->DoChangeChannelImage(m_hChanItem, PRE_PLAY);
}
}
return m_lRealDataID;
}
----------------------------------
我写的C#代码
public delegate void CBRealData(int lRealHandle, E_REALDATA_TYPE eDataType, IntPtr pBuffer, uint lBufSize, IntPtr pUserData);
[DllImport("IPCSDK_Net.dll", CallingConvention = CallingConvention.StdCall)]
public static extern int IPCNET_StartRealData(int lLoginID, ref S_REALDATA_INFO sRealDataInfo, CBRealData fRealData, IntPtr pUserData);
public static void getCallBack(int lRealHandle, E_REALDATA_TYPE eDataType, IntPtr pBuffer, uint lBufSize, IntPtr pUserData)
{
MessageBox.Show("回调成功");
return;
}
private void btnLogin_Click(object sender, EventArgs e)
{
bool init= IPCNET_Init();
bool flag = HDVPLAY_Init();
string ip = "192.168.1.110";
string name = "admin";
string pass = "admin";
int lLoginID = IPCNET_Login(ip, 90, name, pass);
CBRealData callback = new CBRealData(getCallBack);
IntPtr pRealData = Marshal.GetFunctionPointerForDelegate(callback);
S_REALDATA_INFO info = new S_REALDATA_INFO { lChannel = 1, lStreamMode = 0, eEncodeType = E_ENCODE_TYPE.ENCODE_H264 };
int Result = IPCNET_StartRealData(lLoginID, ref info, callback, pRealData);
int error = IPCNET_GetLastError();
}
回调不成功,到底哪里出问题了
#13
你把需要调用.NET的方法用委托传进去试试
#14
你把需要调用.NET的方法用委托传进去试试
我就是用委托传进去的
#15
c# C函数callback 估计没戏.
是一定有戏,用委托即可,我自己就成功过,网上成功的例子就更多了
#16
c# C函数callback 估计没戏.
是一定有戏,用委托即可,我自己就成功过,网上成功的例子就更多了
能不能把你方法放出来看看
#17
大神们出来帮忙啊
#18
把你的 C# 代码用 C++ 调试一下,首先确定你的逻辑没有问题。
如果是 C# 的语法的错误, VS 调试会有信息的。
如果是 C# 的语法的错误, VS 调试会有信息的。
#19
c# C函数callback 估计没戏.
是一定有戏,用委托即可,我自己就成功过,网上成功的例子就更多了
能不能把你方法放出来看看
这个不同的代码具体调用过程会有不同,你可以在工程上点右键属性->调试->启用本机代码调试,直接跟进C++的函数即可,我只有一点可以告诉你,这类情况C#是一定可以成功的
#20
谢谢以上各位,回调已成功,原来是初始化参数时弄错了导致失败