C#不能调用dll中得回调函数

时间:2022-09-27 19:00:09
各位游侠、高手、老大、神仙,帮忙解决一下问题,有问题的地方我都写了注释了

/********************************C++*******************************/
typedef struct VIDEO_INFO
{
int nVideoWidth;/**< 像素宽度 */
int nVideoHeight;/**< 像素高度 */
int nVideoFPS;/**< 每秒多少帧 */
unsigned char data[58];/**< 解码信息头 */
DWORD dataSize;/**< 解码信息头长度 */
struct timeval presentationTime;/**< 解码信息头时间戳 */
}VIDEO_INFO;
enum MSG_lCommand
{
keepalive,/**< 心跳包 */
intrusion_detection,/**< 入侵报警 */
intrusion_update,
stopped_vehicle_detection,
unattended_object_detection,
removed_object_detection,
camera_shift_detection,
alert_display_off,
arm,/**< 设防 */
disarm,/**< 撤防 */
all_detections_cleared,
loss_video_signal,
bad_video_signal,
low_video_signal,
good_video_signal,
dry_contact_enable_change,
dry_contact_arm_change,
dry_contact_status_change,
dry_contact_alarm_state_change,
relay_enable_change,
relay_status_change,
tracking_started,
tripwire_detection,
fence_detection,
loitering_detection,
ptz_lost_track,
ptz_sync_itptz,
device_connect,/**< 设备连上 */
device_dropped,/**< 设备掉线 */
};
typedef struct MSG_INFO 
{
char ip[16];/**< 报警设备IP */
long object_id;/**< 对象ID */
long rule_name;/**< 参考枚举 Rule_name */
long rule_id;/**< 规则ID */
double rel_center_x;
double rel_center_y;
double rel_dimension_x;
double rel_dimension_y;
double rel_velocity_x;
double rel_velocity_y;
long preset_id;
double direction;
double time_in_rule;
double range;
}MSG_INFO;
struct timeval {
        long    tv_sec; 
        long    tv_usec;  
};
typedef void (CALLBACK *MSGCallBack)(LONG lCommand,LONG nID,int nCh, char *pAlarmInfo, DWORD dwBufLen, void* Context);//报警回调函数
typedef void (CALLBACK *fRealDataCallBack) (LONG nStreamID,LONG nID, int nCh, const unsigned char *pBuffer, DWORD dwBufSize,struct timeval presentationTime, void* RealDataCallBackContext);//视频流回调
AIIVS_API void __stdcall AIIVS_Init();//初始化SDK
AIIVS_API LONG __stdcall AIIVS_Connect(char * sIp, int nPort , char * sName , char * sPwd ,MSGCallBack pMsgCallBack = NULL, void * Context = NULL);  //连接IVS设备
AIIVS_API int __stdcall AIIVS_OpenStream(LONG nID , int nCh,fRealDataCallBack pRealDataCallBack = NULL,void *RealDataCallBackContext = NULL);//开启视频流,返回通道流ID
AIIVS_API int __stdcall AIIVS_GetHeadStream(LONG nID , int nCh,VIDEO_INFO *pVideoInfo);//获取视频流头部
IVSPLAY_API BOOL _stdcall IVS_PLAY_Init();//初始化
IVSPLAY_API LONG _stdcall IVS_PLAY_OpenStream(HWND hWnd,VIDEO_INFO *pVideo_info,bool bRealdecode = true);//打开流播放
IVSPLAY_API BOOL _stdcall IVS_PLAY_InputData(LONG nIndex,PBYTE pBuf,DWORD dwBufSize);//输入流



/*********************************C#****************************************/

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct VIDEO_INFO
    {
 public int nVideoWidth;//视频像素宽度
 public int nVideoHeight;//视频像素高度
 public int nVideoFPS;//视频每秒播放帧数
     [MarshalAs(UnmanagedType.ByValArray,SizeConst=58)]
 public byte[] data;//解码头
 public uint dataSize;//解码头长度
 public timeval presentationTime;//解码头时间戳
    }    /** @brief 报警类型枚举 */
    
     public enum MSG_lCommand
    {
        keepalive,/**心跳包 */
        intrusion_detection,/**入侵报警 */
        intrusion_update,
        stopped_vehicle_detection,
        unattended_object_detection,
        removed_object_detection,
        camera_shift_detection,
        alert_display_off,
        arm,/**设防 */
        disarm,/**撤防 */
        all_detections_cleared,
        loss_video_signal,
        bad_video_signal,
        low_video_signal,
        good_video_signal,
        dry_contact_enable_change,
        dry_contact_arm_change,
        dry_contact_status_change,
        dry_contact_alarm_state_change,
        relay_enable_change,
        relay_status_change,
        tracking_started,
        tripwire_detection,
        fence_detection,
        loitering_detection,
        ptz_lost_track,
        ptz_sync_itptz,
        device_connect,/**设备连上 */
        device_dropped,/**设备掉线 */
    };
    [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
    public struct MSG_INFO
    {
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
        public string ip;/**报警设备IP */
        public int object_id;/**对象ID */
        public int rule_name;/**参考枚举 Rule_name */
        public int rule_id;/**规则ID */
        public double rel_center_x;
        public double rel_center_y;
        public double rel_dimension_x;
        public double rel_dimension_y;
        public double rel_velocity_x;
        public double rel_velocity_y;
        public int preset_id;
        public double direction;
        public double time_in_rule;
        public double range;
    }

    public struct timeval
    {
       public int tv_sec;
       public int tv_usec;
    }

        public const string ivsPlay = "IVSPlay.dll";

        [DllImport(ivsPlay)]
        public static extern bool IVS_PLAY_Init();//初始化
        [DllImport(ivsPlay)]
        public static extern int IVS_PLAY_OpenStream(IntPtr hWnd,VIDEO_INFO pVideo_info, bool bRealdecode);
        [DllImport(ivsPlay)]
        public static extern bool IVS_PLAY_InputData(int nIndex,byte[] pBuf, uint dwBufSize);


        public const string aiIvs = "AIIVS.dll";

        [DllImport(aiIvs)]
        public static extern void AIIVS_Init();
        [DllImport(aiIvs)]
        public static extern int AIIVS_Connect(string sIp, int nPort , string sName , string sPwd ,MSGCallBack pMsgCallBack, IntPtr Context);
        [DllImport(aiIvs)]
        public static extern int AIIVS_OpenStream(int nID ,int nCh,fRealDataCallBack pRealDataCallBack, IntPtr RealDataCallBackContext);//开启视频流,返回通道流ID
        [DllImport(aiIvs)]
        public static extern int AIIVS_GetHeadStream(int nID,int nCh,ref VIDEO_INFO pVideoInfo);

        public delegate void MSGCallBack(int lCommand,int nID,int nCh, string pAlarmInfo,uint dwBufLen,IntPtr Context);
        public delegate void fRealDataCallBack(int nStreamID, int nID, int nCh, byte[] pBuffer, uint dwBufSize, timeval presentationTime,IntPtr RealDataCallBackContext);

21 个解决方案

#1




        public IntPtr n_lUserID;
        public IntPtr RealDataCallBackContext;
        public IvsAPI.MSGCallBack MsgBack;
        public IvsAPI.fRealDataCallBack FrdcBack;
        public int ll = 0;
        private void frmVido_Load(object sender, EventArgs e)
        {
            IvsAPI.AIIVS_Init();
            MsgBack = new IvsAPI.MSGCallBack(msgCallBack);
            FrdcBack = new IvsAPI.fRealDataCallBack(frcBack);


            ll = IvsAPI.AIIVS_Connect("192.168.1.15", 80, "admin", "admin",MsgBack,  pictureBox1.Handle);
        }
        private void ListenAlarmThreadProc()
        {
        }
        private void msgCallBack(int lCommand, int nID, int nCh, string pAlarmInfo, uint dwBufLen, IntPtr Context)
        {
            //MessageBox.Show(lCommand.ToString() + pAlarmInfo + "---" + dwBufLen.ToString() + "==========" + Context.ToString());
        }
/*****************************下面的回调函数不执行*******************************************/
        private void frcBack(int nStreamID, int nID, int nCh, byte[] pBuffer, uint dwBufSize, timeval presentationTime,IntPtr RealDataCallBackContext)
        {
            bool bol1 = PlayAPI.IVS_PLAY_InputData(nStreamID, pBuffer, dwBufSize);
            MessageBox.Show("");
        }

        private void button1_Click(object sender, EventArgs e)
        {
            VIDEO_INFO video = new VIDEO_INFO();
            int ii = IvsAPI.AIIVS_OpenStream( ll,  1, FrdcBack,  RealDataCallBackContext);
            int it = IvsAPI.AIIVS_GetHeadStream(ll, 1,ref video);
            bool bolt = PlayAPI.IVS_PLAY_Init();
            int lon = PlayAPI.IVS_PLAY_OpenStream(pictureBox1.Handle,video, true);//报写入内存错误加上ref就不报了,但是这里不是输出参数是传入的值

        }

#2


楼主搞外挂?

#3


IVS_PLAY_OpenStream()传递的参数 第一个 是传递的什么? 怎么是一个控件的句柄?


[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
//有时候小小的设置也会出问题


调试一下 监视一下video对象里是否保存了需要播放的数据.

#4


video里有数据不是video的问题,问题我已经注释出来了另外上面代码部分的
"const unsigned char *pBuffer”如何转成C#

#5


刚在问问上给你回答了,特意上这里再赚点分,哇咔咔。
你要在你的frmVideo_Load函数里面把你声明的FrdcBack回调指针传入到那个AIIVS_OPENStream函数里面,这样,当openstream执行的时候才回触发你的回调

#6


擦,发现你在click事件里面传入了,问题是你第一个参数怎么传了个11,那是个句柄啊

#7


这是C++中应用的回调函数

CString strIP,strUsername,strPssword;
GetDlgItem(IDC_IPADDRESS)->GetWindowText(strIP);
GetDlgItem(IDC_EDIT_USERNAME)->GetWindowText(strUsername);
GetDlgItem(IDC_EDIT_PASSWORD)->GetWindowText(strPssword);
int nRet = AIIVS_Connect((char*)(LPCTSTR)strIP,80,(char*)(LPCTSTR)strUsername,(char*)(LPCTSTR)strPssword,FunCallBackAlarm,this);
int nDeciveID = vinfo[nSelectVideoShow__].nDeciveID;
int nChannel = control_combobox_channel__.GetCurSel() + 1;
//执行回调函数
int nStreamID = AIIVS_OpenStream(nDeciveID,nChannel,FunCallBackVideoStream,&vinfo[nSelectVideoShow__]);
VIDEO_INFO vi;
AIIVS_GetHeadStream(nDeciveID,nChannel,&vi);
int nDecodeID = 1;
nDecodeID = IVS_PLAY_OpenStream(vinfo[nSelectVideoShow__].hWnd,&vi);
//回调函数
void WINAPI FunCallBackVideoStream(LONG nStreamID,LONG nID, int nCh, const unsigned char *pBuffer, DWORD dwBufSize,struct timeval presentationTime, void* RealDataCallBackContext)
{
VIDEO_SHOW_INFO *pViShow_INFO = (VIDEO_SHOW_INFO *)RealDataCallBackContext;
IVS_PLAY_InputData(pViShow_INFO->nDecodeID,(PBYTE)pBuffer,dwBufSize);
}

#8


给你一个正确的例子:

C++:
void TestCallBack(FPTR pf, int value);
void TestCallBack2(FPTR2 pf2, char* value);

C#:
public delegate bool FPtr( int value );
public delegate bool FPtr2( String value );

public class LibWrap
{// Declares managed prototypes for unmanaged functions.
   [ DllImport( "PinvokeLib.dll" )]
   public static extern void TestCallBack( FPtr cb, int value );   
   [ DllImport( "PinvokeLib.dll" )]
   public static extern void TestCallBack2( FPtr2 cb2, String value );   
}

public class App
{
   public static void Main()
   {
      FPtr cb = new FPtr( App.DoSomething );
      LibWrap.TestCallBack( cb, 99 );
      FPtr2 cb2 = new FPtr2( App.DoSomething2 );
      LibWrap.TestCallBack2( cb2, "abc" );
   }
   
   public static bool DoSomething( int value )
   {
      Console.WriteLine( "\nCallback called with param: {0}", value );
      …
   }
   public static bool DoSomething2( String value )
   {
      Console.WriteLine( "\nCallback called with param: {0}", value );
      …
   }   
}


你先对比看看,能不能找不问题!

#9


就用楼上的使用委托才行,我是在猪八戒看到100块任务过来看看的
猪八戒提交

#10


就用楼上的使用委托才行,我是在猪八戒看到100块任务过来看看的
猪八戒提交

const unsigned char *pBuffer
你试一下转成string

#11


可以的,看你怎么调用了

#12


"sdl2005lyx"我的例子跟你的一样
在这个程序里有两个回调函数第一个回调函数已经执行成功了,但是第二个回调函数“fRealDataCallBack“就是执行不成功,是不是哪个数据类型错了

#13


懂了,上QQ

#14


“但是第二个回调函数“fRealDataCallBack“就是执行不成功”,
这个回调函数执行没有?

你在这个方法:
 private void frcBack(int nStreamID, int nID, int nCh, byte[] pBuffer, uint dwBufSize, timeval presentationTime,IntPtr RealDataCallBackContext)
        {
            bool bol1 = PlayAPI.IVS_PLAY_InputData(nStreamID, pBuffer, dwBufSize);
            MessageBox.Show("");
        }

入口出设置断点!跟进去!

如是是:bool bol1 = PlayAPI.IVS_PLAY_InputData(nStreamID, pBuffer, dwBufSize);
执行不成功,不知道你是否有VC的这个工程,有的话就好办:

两个方法跟进到VC的代码里;
1、启动C#这边工程属性:在调试一栏:勾启动非托管代码调试!你用F11就会进入VC工程。

2、直接把net的exe程序做为VC工程的外挂测试程序:
   断点就设置在Vc的这个函数:PlayAPI.IVS_PLAY_InputData入口,F5启动你的VC工程

这样,你就可以一步一步查看VC这边执行的步骤,找到出问题的地方!
   

#15


回答“sdl2005lyx”
frcBack根本就不执行,就好像没有订阅事件一样,frcBack就好像与程序无关一样,断点根本就不进入frcBack里面

#16


这个就比较头晕了!

#17


你按我说的方法测试了吗?在VC的工程启动测试,不要在net这边测试,
断点就放在VC的函数:AIIVS_OpenStream入口处,F5启动调试,一步一步一进行调试,
问题应该能查出来!

#18


就是F5进行调试的,数据与vc的一模一样,输出的信息也是一样的就是不进入那个回调函数,估计是没救了

#19


楼主,到现在你都明白我的意思:

直接用VC的工程来调试,而且是在VC这边启动!net的exe只不过是一个外挂测试程序而已!

还有,这类问题,是比较复杂,感觉你每次都只给20分,好像很不对称喔!

#20


问题没有解决,不太明白你说的VC启动时什么意思,我这边有VC程序的工程也是用的调试启动的但是那个api函数是封装好的根本无法跟踪进入,只能从输出看到点信息,我不太懂你说的意思
总的要谢谢“sdl2005lyx”分确实很少,因为我没有那么多得分数,不过要是能解决问题的话我可以用RMB解决,细节可以加我QQ:33850826详谈

今天结贴了,下次一定高分解决问题

#21


你可以把这个API的函数,已经VC那边使用的Demo发给我,看看能不能帮你搞定!
邮箱: sdl2002lyx@163.com

#1




        public IntPtr n_lUserID;
        public IntPtr RealDataCallBackContext;
        public IvsAPI.MSGCallBack MsgBack;
        public IvsAPI.fRealDataCallBack FrdcBack;
        public int ll = 0;
        private void frmVido_Load(object sender, EventArgs e)
        {
            IvsAPI.AIIVS_Init();
            MsgBack = new IvsAPI.MSGCallBack(msgCallBack);
            FrdcBack = new IvsAPI.fRealDataCallBack(frcBack);


            ll = IvsAPI.AIIVS_Connect("192.168.1.15", 80, "admin", "admin",MsgBack,  pictureBox1.Handle);
        }
        private void ListenAlarmThreadProc()
        {
        }
        private void msgCallBack(int lCommand, int nID, int nCh, string pAlarmInfo, uint dwBufLen, IntPtr Context)
        {
            //MessageBox.Show(lCommand.ToString() + pAlarmInfo + "---" + dwBufLen.ToString() + "==========" + Context.ToString());
        }
/*****************************下面的回调函数不执行*******************************************/
        private void frcBack(int nStreamID, int nID, int nCh, byte[] pBuffer, uint dwBufSize, timeval presentationTime,IntPtr RealDataCallBackContext)
        {
            bool bol1 = PlayAPI.IVS_PLAY_InputData(nStreamID, pBuffer, dwBufSize);
            MessageBox.Show("");
        }

        private void button1_Click(object sender, EventArgs e)
        {
            VIDEO_INFO video = new VIDEO_INFO();
            int ii = IvsAPI.AIIVS_OpenStream( ll,  1, FrdcBack,  RealDataCallBackContext);
            int it = IvsAPI.AIIVS_GetHeadStream(ll, 1,ref video);
            bool bolt = PlayAPI.IVS_PLAY_Init();
            int lon = PlayAPI.IVS_PLAY_OpenStream(pictureBox1.Handle,video, true);//报写入内存错误加上ref就不报了,但是这里不是输出参数是传入的值

        }

#2


楼主搞外挂?

#3


IVS_PLAY_OpenStream()传递的参数 第一个 是传递的什么? 怎么是一个控件的句柄?


[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
//有时候小小的设置也会出问题


调试一下 监视一下video对象里是否保存了需要播放的数据.

#4


video里有数据不是video的问题,问题我已经注释出来了另外上面代码部分的
"const unsigned char *pBuffer”如何转成C#

#5


刚在问问上给你回答了,特意上这里再赚点分,哇咔咔。
你要在你的frmVideo_Load函数里面把你声明的FrdcBack回调指针传入到那个AIIVS_OPENStream函数里面,这样,当openstream执行的时候才回触发你的回调

#6


擦,发现你在click事件里面传入了,问题是你第一个参数怎么传了个11,那是个句柄啊

#7


这是C++中应用的回调函数

CString strIP,strUsername,strPssword;
GetDlgItem(IDC_IPADDRESS)->GetWindowText(strIP);
GetDlgItem(IDC_EDIT_USERNAME)->GetWindowText(strUsername);
GetDlgItem(IDC_EDIT_PASSWORD)->GetWindowText(strPssword);
int nRet = AIIVS_Connect((char*)(LPCTSTR)strIP,80,(char*)(LPCTSTR)strUsername,(char*)(LPCTSTR)strPssword,FunCallBackAlarm,this);
int nDeciveID = vinfo[nSelectVideoShow__].nDeciveID;
int nChannel = control_combobox_channel__.GetCurSel() + 1;
//执行回调函数
int nStreamID = AIIVS_OpenStream(nDeciveID,nChannel,FunCallBackVideoStream,&vinfo[nSelectVideoShow__]);
VIDEO_INFO vi;
AIIVS_GetHeadStream(nDeciveID,nChannel,&vi);
int nDecodeID = 1;
nDecodeID = IVS_PLAY_OpenStream(vinfo[nSelectVideoShow__].hWnd,&vi);
//回调函数
void WINAPI FunCallBackVideoStream(LONG nStreamID,LONG nID, int nCh, const unsigned char *pBuffer, DWORD dwBufSize,struct timeval presentationTime, void* RealDataCallBackContext)
{
VIDEO_SHOW_INFO *pViShow_INFO = (VIDEO_SHOW_INFO *)RealDataCallBackContext;
IVS_PLAY_InputData(pViShow_INFO->nDecodeID,(PBYTE)pBuffer,dwBufSize);
}

#8


给你一个正确的例子:

C++:
void TestCallBack(FPTR pf, int value);
void TestCallBack2(FPTR2 pf2, char* value);

C#:
public delegate bool FPtr( int value );
public delegate bool FPtr2( String value );

public class LibWrap
{// Declares managed prototypes for unmanaged functions.
   [ DllImport( "PinvokeLib.dll" )]
   public static extern void TestCallBack( FPtr cb, int value );   
   [ DllImport( "PinvokeLib.dll" )]
   public static extern void TestCallBack2( FPtr2 cb2, String value );   
}

public class App
{
   public static void Main()
   {
      FPtr cb = new FPtr( App.DoSomething );
      LibWrap.TestCallBack( cb, 99 );
      FPtr2 cb2 = new FPtr2( App.DoSomething2 );
      LibWrap.TestCallBack2( cb2, "abc" );
   }
   
   public static bool DoSomething( int value )
   {
      Console.WriteLine( "\nCallback called with param: {0}", value );
      …
   }
   public static bool DoSomething2( String value )
   {
      Console.WriteLine( "\nCallback called with param: {0}", value );
      …
   }   
}


你先对比看看,能不能找不问题!

#9


就用楼上的使用委托才行,我是在猪八戒看到100块任务过来看看的
猪八戒提交

#10


就用楼上的使用委托才行,我是在猪八戒看到100块任务过来看看的
猪八戒提交

const unsigned char *pBuffer
你试一下转成string

#11


可以的,看你怎么调用了

#12


"sdl2005lyx"我的例子跟你的一样
在这个程序里有两个回调函数第一个回调函数已经执行成功了,但是第二个回调函数“fRealDataCallBack“就是执行不成功,是不是哪个数据类型错了

#13


懂了,上QQ

#14


“但是第二个回调函数“fRealDataCallBack“就是执行不成功”,
这个回调函数执行没有?

你在这个方法:
 private void frcBack(int nStreamID, int nID, int nCh, byte[] pBuffer, uint dwBufSize, timeval presentationTime,IntPtr RealDataCallBackContext)
        {
            bool bol1 = PlayAPI.IVS_PLAY_InputData(nStreamID, pBuffer, dwBufSize);
            MessageBox.Show("");
        }

入口出设置断点!跟进去!

如是是:bool bol1 = PlayAPI.IVS_PLAY_InputData(nStreamID, pBuffer, dwBufSize);
执行不成功,不知道你是否有VC的这个工程,有的话就好办:

两个方法跟进到VC的代码里;
1、启动C#这边工程属性:在调试一栏:勾启动非托管代码调试!你用F11就会进入VC工程。

2、直接把net的exe程序做为VC工程的外挂测试程序:
   断点就设置在Vc的这个函数:PlayAPI.IVS_PLAY_InputData入口,F5启动你的VC工程

这样,你就可以一步一步查看VC这边执行的步骤,找到出问题的地方!
   

#15


回答“sdl2005lyx”
frcBack根本就不执行,就好像没有订阅事件一样,frcBack就好像与程序无关一样,断点根本就不进入frcBack里面

#16


这个就比较头晕了!

#17


你按我说的方法测试了吗?在VC的工程启动测试,不要在net这边测试,
断点就放在VC的函数:AIIVS_OpenStream入口处,F5启动调试,一步一步一进行调试,
问题应该能查出来!

#18


就是F5进行调试的,数据与vc的一模一样,输出的信息也是一样的就是不进入那个回调函数,估计是没救了

#19


楼主,到现在你都明白我的意思:

直接用VC的工程来调试,而且是在VC这边启动!net的exe只不过是一个外挂测试程序而已!

还有,这类问题,是比较复杂,感觉你每次都只给20分,好像很不对称喔!

#20


问题没有解决,不太明白你说的VC启动时什么意思,我这边有VC程序的工程也是用的调试启动的但是那个api函数是封装好的根本无法跟踪进入,只能从输出看到点信息,我不太懂你说的意思
总的要谢谢“sdl2005lyx”分确实很少,因为我没有那么多得分数,不过要是能解决问题的话我可以用RMB解决,细节可以加我QQ:33850826详谈

今天结贴了,下次一定高分解决问题

#21


你可以把这个API的函数,已经VC那边使用的Demo发给我,看看能不能帮你搞定!
邮箱: sdl2002lyx@163.com