首页 新闻 会员 周边 捐助

C++ 怎么才能拥有回调函数的对象?像C#一样

0
悬赏园豆:10 [已解决问题] 解决于 2021-11-11 10:42

C#代码

        private void RealPlayAndPTZDemo_Load(object sender, EventArgs e)
        {
            m_DisConnectCallBack = new fDisConnectCallBack(DisConnectCallBack);
            m_ReConnectCallBack = new fHaveReConnectCallBack(ReConnectCallBack);
            m_RealDataCallBackEx2 = new fRealDataCallBackEx2(RealDataCallBackEx);
            m_SnapRevCallBack = new fSnapRevCallBack(SnapRevCallBack);
            try
            {
                NETClient.Init(m_DisConnectCallBack, IntPtr.Zero, null);
                NETClient.SetAutoReconnect(m_ReConnectCallBack, IntPtr.Zero);
                NETClient.SetSnapRevCallBack(m_SnapRevCallBack, IntPtr.Zero);
                InitOrLogoutUI();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                Process.GetCurrentProcess().Kill();
            }
        }


        #region CallBack 回调
        private void DisConnectCallBack(IntPtr lLoginID, IntPtr pchDVRIP, int nDVRPort, IntPtr dwUser)
        {
            this.BeginInvoke((Action)UpdateDisConnectUI);
        }

        private void UpdateDisConnectUI()
        {
            this.Text = "RealPlayAndPTZDemo(实时预览与云台Demo) --- Offline(离线)";
        }

        private void ReConnectCallBack(IntPtr lLoginID, IntPtr pchDVRIP, int nDVRPort, IntPtr dwUser)
        {
            this.BeginInvoke((Action)UpdateReConnectUI);
        }
        private void UpdateReConnectUI()
        {
            this.Text = "RealPlayAndPTZDemo(实时预览与云台Demo) --- Online(在线)";
        }

        private void RealDataCallBackEx(IntPtr lRealHandle, uint dwDataType, IntPtr pBuffer, uint dwBufSize, IntPtr param, IntPtr dwUser)
        {
            //do something such as save data,send data,change to YUV. 比如保存数据,发送数据,转成YUV等.
        }

        private void SnapRevCallBack(IntPtr lLoginID, IntPtr pBuf, uint RevLen, uint EncodeType, uint CmdSerial, IntPtr dwUser)
        {
            string path = AppDomain.CurrentDomain.BaseDirectory + "capture";
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }
            if (EncodeType == 10) //.jpg
            {
                DateTime now = DateTime.Now;
                string fileName = "async"+ CmdSerial.ToString()+ ".jpg";
                string filePath = path + "\\" + fileName;
                byte[] data = new byte[RevLen];
                Marshal.Copy(pBuf, data, 0, (int)RevLen);
                using (FileStream stream = new FileStream(filePath, FileMode.OpenOrCreate))
                {
                    stream.Write(data, 0, (int)RevLen);
                    stream.Flush();
                    stream.Dispose();
                }
            }
        }
        #endregion
echo_lovely的主页 echo_lovely | 小虾三级 | 园豆:1534
提问于:2021-11-04 09:51
< >
分享
最佳答案
1

给你个示例,自己实现。

#include <iostream>

void callback0()
{
	puts("this is a callback!");
}

void callback1()
{
	puts("hello the callback!");
}

void test(intptr_t callback)
{
	_asm {
		call callback;
	}
}

int main(int argc, char* argv[])
{
	test((intptr_t)callback0);

	system("pause");
	return 0;
}
收获园豆:8
寂静的羽夏 | 老鸟四级 |园豆:2091 | 2021-11-04 16:58

这是回调对象吗?这个类会被使用多次,这样写的话,默认static的吧

echo_lovely | 园豆:1534 (小虾三级) | 2021-11-04 17:06

@echo_lovely: 我这个示例是告诉你,回调函数的本质是什么。回调函数不过是个函数指针而已,用C++写就不要受C#的面向对象的束缚。至于是不是静态,就是你的设计了。

寂静的羽夏 | 园豆:2091 (老鸟四级) | 2021-11-04 17:09

@echo_lovely: 回调对象不过是把回调函数封装了一下

寂静的羽夏 | 园豆:2091 (老鸟四级) | 2021-11-04 17:09

@寂静的羽夏: 我也理解它是个函数指针,我只不过不会写,因为没有接触过c++,项目本来是C#的,现在突然要转为Linux版的,用QT开发,稍微难一些的就不会了……

echo_lovely | 园豆:1534 (小虾三级) | 2021-11-04 17:13

@寂静的羽夏: 因为c++也支持面向对象,我都直接把它当Java用了……

echo_lovely | 园豆:1534 (小虾三级) | 2021-11-04 17:16

@echo_lovely:
这个是VS写的,应该和QT区别不大,自己改改吧。这个举例自行参考:

#include <iostream>

typedef void (*Func)();

class CallBackClass
{
public:
	CallBackClass(Func callback);
	static void Invoke(CallBackClass* callbackcls);
private:
	Func callback = NULL;
};

CallBackClass::CallBackClass(Func callback)
{
	if (!callback)
	{
		throw "函数地址为空";
	}
	this->callback = callback;
}


void CallBackClass::Invoke(CallBackClass* callbackcls)
{
	if (!callbackcls->callback)
	{
		throw "函数地址为空";
	}
	callbackcls->callback();
}

void callback()
{
	puts("this is a callback!");
}

int main(int argc, char* argv[])
{
	
	CallBackClass* callcls = new CallBackClass(callback);
	CallBackClass::Invoke(callcls);

	delete callcls;
	system("pause");
	return 0;
}
寂静的羽夏 | 园豆:2091 (老鸟四级) | 2021-11-04 17:23

@echo_lovely: C++ 并不是完全的面向对象,它只是有了面向对象的概念,可以面向对象。它的面向对象的实现完全比不上 Java。

寂静的羽夏 | 园豆:2091 (老鸟四级) | 2021-11-04 17:25

@echo_lovely: 你这不是废话,回调函数本来就是通过函数指针实现的,你要是调用设置了回调函数的函数,当然会被多次调用。你看到的实际应用中的回调函数,一般是由事件触发的,而事件是由操作系统或者库产生的。
试问,你按一个手机按键,通过系统捕捉触摸事件,回调提示信息。假如你按了多次,难不成系统只给你永远只显示一次?

明明1109 | 园豆:213 (菜鸟二级) | 2021-11-11 10:33

@明明1109: 已经干明白回调函数了
我这边多个视频对象会调同一个回调,然后视频数据又不一样,然后就在一个窗口闪啊闪……

echo_lovely | 园豆:1534 (小虾三级) | 2021-11-11 10:41
其他回答(2)
0

回调函数需要使用函数指针来实现

#include<stdio.h>
void f1(void){
  printf("f1\n");
}
void f2(void){
  printf("f2\n");
}
void fp(void (*f)()){
  (*f)();
}
int main(){
  fp(f1);
}

以上是最简单的函数指针示例,大概就是类似的思路。

收获园豆:2
计算机知识杂谈 | 园豆:470 (菜鸟二级) | 2021-11-04 21:00
0

std::function

Smalldy | 园豆:482 (菜鸟二级) | 2022-06-17 14:07
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册