精华内容
下载资源
问答
  • 回调函数机制 使用了 函数指针。...3.定义一个注册回调函数 void SetCallback(func_ptr ptr);, 其中 func_ptr 是一个函数指针类型,之后会把一个回调函数地址(函数名func)赋值给 ptr; func_ptr m_p

    回调函数机制 使用了 函数指针
    步骤:

    • 1.定义一个函数指针,如typedef void (*func_ptr)(std::string str);
    • 2.定义一个 回调函数 void func(std::string str),需要注意的是,回调函数必须和前面定义的函数指针参数类型和参数个数一致
    • 3.定义一个注册回调函数 void SetCallback(func_ptr ptr);, 其中 func_ptr 是一个函数指针类型,之后会把一个回调函数地址(函数名func)赋值给 ptr
    typedef void (*func_ptr)(std::string str);
    
    class Test{
     func_ptr m_ptr;
    
     void SetCallback(func_ptr ptr){
        this->m_ptr = ptr;  // 注册回调函数把传入的函数指针 ptr 赋值给了成员函数m_ptr
      }
    }
    
    // 在其他地方或其他cpp文件定义一个下面这样的函数 
    void func(std::string str)
    {
    	/*code*/
    }
    
    int main(){
    Test test;
    test.SetCallback(func);
    }
    

    如:SetCallback(func) 把 一个已经定义的函数func的函数地址 赋值给 函数指针 m_ptr,这样就相当于注册了回调函数,当我们在对象的其他位置就可以直接以函数形式调用m_ptr("Jack")了。
    所以注册回调函数SetCallback(func_ptr ptr)的作用就是 给成员变量函数指针进行赋值,相当于对是对对象实现回调函数,以便后面直接调用该回调函数。

    后来我看到我同事的一篇博客,写得挺不错,粘贴于此

    原文地址:c++两个普通类利用回调函数传递信息https://blog.csdn.net/M_Alan_walker/article/details/108320295

           如果要在两个class对象之间传递数据,最简单直接的方法在一个类中定义一个全局变量,然后在另一个类里面extern这个变量,这样就等于这个全局变量同时作用于两个类对象中,这样做能暂时解决问题,然而可能会出现新的问题,比如,代码的复用性不好,全局变量会在main之前初始化,增加了程序的负担;还有一个致命的问题,如果是多线程程序,就需要加锁保证同一时刻只能有一个对象在访问修改这个全局变量,程序的效率可能会下降,当然如果定义的全局变量过多,由于加锁不慎很可能会导致死锁,致使程序奔溃,今天介绍一中很实用的办法,线程安全并且封装性好;
    先看代码

    #include <iostream>    
    
    using namespace std;  
    
    typedef void(*CallBack)(char* s);
    
    class A{
    public:
      void setCbk(CallBack call_back){
          this->_my_call_back = call_back;
          _my_call_back("123456789");
      }
    public:
      A(){}
      ~A(){}
      CallBack _my_call_back;
    };
    
    class  B{
    public:
      static void OnCallBack(char * s){
          cout << "gxs s:" << s << endl;
      }
    
    public:
      B(){        
          A a;
          a.setCbk(B::OnCallBack);	//注册回调函数
      }
      ~B(){}
    };
    
    int main()
    {
      B b;
      return 0;
    }
    

           首先typedef void(*CallBack)(char* s)申明了一个函数指针,这个CallBack指针指向一个返回值是void类型参数是char*的函数;那怎么才能让类Achar*数据传到类B来呢,读代码就知道了,很简单在类A里面定义一个CallBack的成员变量,然后把类BOnCallBack的地址赋值给ACallBack,这样ACallBack在执行的时候就会执行BOnCallBack的代码了;

           该怎么理解呢? 理解这个原理首先得理解函数指针的含义,顾名思义,函数指针它是一个指针,这个指针指向的是一个函数。这个意思就是,你可以通过一个指针调用一个函数,所以你想调用别的类的函数,就要把它类里面这个函数的地址获取到赋值到你类里面的函数指针。

           其实,这是回调函数最原始的做法,很多IDE已经开发出非常高效便捷的回调形式,最经典的莫过于Qt信号槽机制了,它做的太好了,好到你可以任意的设置回调的接口而不必关心这个谁去发起这个连接,换句话说就是: 你在Class A中设置回调的时候class B这个对象不存在也没关系

    展开全文
  • Lua注册回调函数实现

    2020-05-27 12:07:52
    这个 注册回调函数 的实现就是类似函数的 重定义 一样 ,首先定义一个CallBack的表 local sis_event_cb = {} 之后建立一个注册回调的事件注册的函数 function msis:on_sis_event(event, cb_func) sis_event_cb...
    这个 注册回调函数 的实现就是类似函数的 重定义 一样 ,首先定义一个CallBack的表
    local sis_event_cb = {}
    
    之后建立一个注册回调的事件注册的函数
    function msis:on_sis_event(event, cb_func)
        sis_event_cb[event] = cb_func
        print("CallBack Set")
    end
    
    
    最后实现一个回调函数
    local function handshake_cb(result, message, module_firmware_ver, module_firmware_url)
         print("hello")
    end
    
    local mytable = nil
    local msis = {}
    msis.__index = msis
    
    local sis_event_cb = {}
    
    --事件注册的函数
    function msis:on_sis_event(event, cb_func)
        sis_event_cb[event] = cb_func
        print("CallBack Set")
    end
    
    --回调函数的实现
    local function handshake_cb(result, message, module_firmware_ver, module_firmware_url)
         print("hello")
    end
    
    --实现函数,主要是穿插在事件函数中
    function msis:handshake() 
        print("Handshake Task Run")
    end
    
    msis:on_sis_event("handshake", handshake_cb)
    sis_event_cb["handshake"](true , "CallBack")
    msis:handshake() 
    

    在这里插入图片描述

    展开全文
  • c++ 注册回调函数研究

    万次阅读 2016-08-19 15:18:03
    连接高层和底层就叫注册回调函数。高层程序C1调用底层程序C2,而在底层程序C2 又调用了高层程序C2的callback函数,那么这个callback函数对于高层程序C1来说就是回调函数。 在设计模式中这个方式叫回调模式。 二 ...

    一 何为注册回调 

       注册回调简单解释就是一个高层调用底层,底层再过头来用高层,这个过程就叫注册回调, 连接高层和底层就叫注册回调函数。高层程序C1调用底层程序C2,而在底层程序C2 又调用了高层程序C2的callback函数,那么这个callback函数对于高层程序C1来说就是回调函数。 在设计模式中这个方式叫回调模式。


    二 注册回调函数的实例:

    //底层程序 C2

    #include<iostream>
    
    using namespace std;
    
    class CCallback
    {
    public:
    	virtual void onCallbackFunc(int value,int type) =0;	
    };
    
    class ClassA
    {
    public: 
    	ClassA(CCallback *pCallbackFunc)
    	{
    		m_pCallBack = pCallbackFunc;	
    	}
    
    	void showValue()
    	{
    		m_pCallBack->onCallbackFunc(15,0);
    		m_pCallBack->onCallbackFunc(17,1);
    	}
    private:
    	CCallback *m_pCallBack;
    
    };
    

    //高层程序 C1

    #include<iostream>
    #include"ClassA.hpp"
    using namespace std;
    
    class ClassB : public CCallback
    {
    public:
    	ClassB()
    	{
    		m_ClassA = new ClassA(this);				
    	}
    
    	void onCallbackFunc(int value,int type)
    	{
    		if(type == 0)
    		{
    			cout<<"Typ_ZERO =  "<< value<<endl;
    		}
    		else
    		{
    			cout<<"Typ_Other =  "<< value<<endl;
    		}
    	}
    
    	void TestShowData()
    	{
    		m_ClassA->showValue();
    	}
    public:
    	ClassA * m_ClassA;
    };
    


    //主程序 main 

    #include "stdafx.h"
    #include"ClassB.hpp"
    
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    
    	ClassB *m_classB =new ClassB();
    	
    	m_classB->TestShowData();
    
    	system("pause:");
    	return 0;
    }
    

    测试结果:



    上面就是一个简单的注册回调的过程。


    三 : 注册回调有何作用

     注册回调 可以让调用者与被调用者分开。调用者不关心谁是被调用者,所有它需知道的,只是存在一个具有某种特定原型、某些限制条件(如返回值为int)的被调用函数。





    展开全文
  • 3、动态库里面有个回调函数机制,使用用DLL时,需要注册回调函数,回调函数的参数有一个指向结构体的指针 4、上位机实现的回调函数会打印指针内的内容 5、上位机调用debug版的DLL时,内容显示正确,而调用 release...

    最近遇到个比较奇葩的问题,场景是这样

    1、上位机程序是用 delphi 编写的

    2、动态库是用 vc++ 编写的

    3、动态库里面有个回调函数机制,使用用DLL时,需要注册回调函数,回调函数的参数有一个指向结构体的指针

    4、上位机实现的回调函数会打印指针内的内容

    5、上位机调用debug版的DLL时,内容显示正确,而调用 release 版的 DLL 时,内容显示的是乱码

     

    解决过程入下

    1、对比 DLL 中 debug 和 relese 的编译选项,找出影响这个结果的那一项

    2、最后发现是 “属性”->“C/C++”->“常规”->“调试信息格式” 这一项 出现的影响,

    debug 版的值是  “用于“编辑并继续”的程序数据库 (/ZI)”

    release 版的值是 “程序数据库 (/Zi)”

    3、如果把release版的值也修改成   “用于“编辑并继续”的程序数据库 (/ZI)”, 则上位机显示得内容也变得正常了

    但是为什么这两个的值不同会导致内容显示也不同,这个就不清楚了。

     

    由于实在是不甘心,就走到这一步,感觉问题不一定在DLL,我又从上位机那里入手

    1、从现象来看,内容打印错误,但是结构体大小是正确的

    2、问题可能出现在结构体在内存中的排布顺序

    3、能影响到参数在内存中的排布顺序的,很可能就是调用约定了

    4、检查回调函数的声明和定义,都没有显式地声明调用约定,估计问题就出在这里了

    5、默认情况下,vc++如果没有显式声明调用约定,则默认的调用约定就是 _cdecl

    6、而delphi的调用则是 register

    7、尝试着在delphi 上位机中显式声明调用约定 _cdecl ,重新编译

    8、再次执行上位机,显示内容正确!

     

    回顾下来,就是因为没有在 delphi 中指定调用约定,导致了这次的 “乱码” 事故,大家往后在写代码的时候要多多注意才是。

    后面去查了一下,关于编译选项的说明

    /Z7、/Zi、/ZI(调试信息格式)

    • 2008/08/18

    更新:2007 年 11 月

    选择为程序创建的调试信息的类型,并选择是将此信息保存在对象 (.obj) 文件还是程序数据库 (PDB) 中。

    复制

    /Z{7|i|I}
    

    备注

    下表描述了这些选项。


    • 不产生任何调试信息,因此编译较快。

    • /Z7
      生成包含用于调试器的完整符号调试信息的 .obj 文件。符号调试信息包括变量的名称和类型以及函数和行号。不会生成任何 .pdb 文件。

      对于第三方库的发布者,不生成 .pdb 文件是一个优点。但是,在链接和调试期间,用于预编译头的 .obj 文件是必需的。如果 .pch 对象文件中只有类型信息(没有代码),则还必须使用 /Yl(为调试库插入 PCH 引用) 进行编译。

    • /Zi
      产生包含用于调试器的类型信息和符号调试信息的程序数据库 (PDB)。符号调试信息包括变量的名称和类型以及函数和行号。

      /Zi 不影响优化。但是,/Zi 的确暗示了 /debug;有关更多信息,请参见 /DEBUG(生成调试信息)

      类型信息放置在 .pdb 文件而不是 .obj 文件中。

      可以将 /Gm(启用最小重新生成) 和 /Zi 结合使用,但使用 /Z7 编译时不能使用 /Gm

      使用 /Zi 和 /clr 编译时,DebuggableAttribute 属性将不会被放入程序集元数据中;如果要使用该属性,则必须在源代码中指定它。该属性可影响应用程序的运行时性能。有关 Debuggable 属性如何影响性能以及如何减轻性能影响的更多信息,请参见令映像更易于调试

    • /ZI
      以支持“编辑并继续”功能的格式产生如上所述的程序数据库。如果想使用“编辑并继续”调试,则必须使用此选项。因为大多数优化与“编辑并继续”不兼容,所以使用 /ZI 会禁用代码中的所有 #pragma optimize 语句。

      /ZI 会导致在编译中使用 /Gy(启用函数级链接)

      /ZI 与 /clr(公共语言运行库编译) 不兼容。

      表 1
      说明:

      /ZI 只可用于面向 x86 的编译器中;此编译器选项不可用于面向 x64 或 Itanium 处理器系列 (IPF) 的编译器中。

    编译器将程序数据库命名为 项目.pdb。如果编译没有项目的文件,则编译器将创建名为 VCx0.pdb. 的数据库,其中 x 是正在使用的 Visual C++ 的主版本。编译器将 PDB 的名称嵌入每个使用此选项创建的 .obj 文件中,从而使调试器了解符号和行号信息的位置。当使用此选项时,.obj 文件将较小,因为调试信息存储在 .pdb 文件中而不是 .obj 文件中。

    如果从使用此选项编译的对象创建库,则在将库链接到程序时,关联 .pdb 文件必须可用。因此,如果发布此库,就必须发布 PDB。

    若要不使用 .pdb 文件创建包含调试信息的库,必须选择编译器的 C 7.0 兼容 (/Z7) 选项。如果使用预编译头选项,则预编译头和其他源代码的调试信息都放在 PDB 中。指定了“程序数据库”选项时将忽略 /Yd 选项。

    原因可能和 “禁用代码中的所有 #pragma optimize 语句” 这个有关,深层次的原因目前还想不出来。

    展开全文
  • halcon外触发get_framegrabber_callback注册回调函数方法,c#代码
  • C++的函数代码如下,注册接口为cppfunction,回调函数为pFunc,其参数为PARA结构体。 ``` void cppfunction(void (*pFunc)(PARA*)) ``` 通过动态注册JNI的方式,cppfunction的函数签名该如何书写?直接将其参数标为...
  • (六)注册回调函数

    2019-08-21 16:50:50
    glultReshapeFunc 注册当前窗口的形状变化回调函数 glutMouseFunc 注册当前窗口的鼠标回调函数 glutMotionFunc 设置移动回调函数 glutIdleFunc 设置全局的空闲回调函数 glutVisibilityFunc 设置当前窗口的可视回调...
  • 注册回调函数实现方法

    千次阅读 2019-04-12 12:34:07
    回调函数(callback):回调函数就是在框架设计之初留下一个还未实现的接口,供后来人去实现(不实现也没事)。也可以理解在别人的函数中“插一脚”,有一种“你的过去我来不及参与,你的未来我奉陪到底”。 看代码...
  • VC中注册回调函数 回调函数的声明如下: extern "C" __declspec(dllexport) void _stdcall initialize(HWND gmyhWnd,const char* fileName, const char* eventFileName,const char* dbFilePath,...
  • OpenGL的注册回调函数 void glutDisplayFunc(void (*func)(void) ); 为当前窗口设置显示回调函数 void glutOverlayDisplayFunc(void (*func)(void) ); 注册当前窗口的重叠层的显示回调函数 void ...
  • 注册回调函数运用

    2019-11-14 18:12:34
    1.注册函数 2.注册函数的原型 3.函数指针的原型 4.全局搜索这个函数指针 5.m_cb_table是什么样子的 6.再全局搜索m_cb_table 7.被注册函数的就是在这里传入参数运行 注意:当函数指针传入...
  • 一个Demo,描述了C#如何在C++中注册函数回调
  • # 而是等外部通过Test类的某个方法传入回调函数(这个行为叫注册回调函数)**/ def feature(self): self.callback() def register_callback(self, func): self.callback = func return func test = Test() ...
  • 所谓函数指针,首先是一个指针,不过它是指向存储函数入口地址的指针,这类似于一个数组char aa[5]; aa是指向数组的首地址(也可理解为数组的入口地址)。而这个指针是指向函数存储的内存。 示例代码---两种基本...
  • GLUT-注册回调函数

    2012-11-14 08:42:13
    void glutDisplayFunc(void (*func)(void) ); 为当前窗口设置显示回调函数 void glutOverlayDisplayFunc...注册当前窗口的重叠层的显示回调函数 void glutReshapeFunc(void (*Func)(int width, int height) ); ...
  • C语言注册回调函数例子

    千次阅读 2018-08-27 14:56:26
    /* 函数指针 */ typedef int (*fcb_func)(int a, int b); typedef struct mydata { int a, b; fcb_func fcb; /* 函数管理器 */ } mydata_t; /* 创建时传入相应的函数管理器 */ mydata_t* mydata_create(fcb_...
  • 注册函数表/** * Virtual function table each FIB entry source will register */ typedef struct fib_entry_src_vft_t_ { fib_entry_src_init_t fesv_init; fib_entry_src_deinit_t fesv_deinit; fib_ent
  • 里可以找到回调函数注册函数: zclGeneral_RegisterCmdCallbacks(SAMPLELIGHT_ENDPOINT, &zclSampleLight_CmdCallbacks );  在该函数里需要理解两个静态全局指针结构体变量和两个函数: (1) 两个变量(查看它...
  • 注册回调函数处理SQLITE_BUSY错误

    千次阅读 2010-06-01 18:34:00
     这个函数设置了一个回调函数,当试图打开一个在另一个线程或进程中被锁住的表时,该回调函数可能会被调用。 (译注:这里用的是"可能"被调用,后面会有解译) 当遇到数据库被锁时,如果回调函数是NULL,那么...
  • cocos2d-x内部使用tolua进行lua绑定,但是引擎并没有提供一个通用的接口让我们可以把一个lua函数注册给C++层面的回调事件。翻看引擎的lua绑定代码,我们可以仿照引擎中的方法来做。值得吐槽的是,这套流程在开发中...
  • 视频采集卡采集视频注册回调函数不成功,m_pVRControl返回一直失败,视频采集是成功的,能正常显示,这个是什么问题?是否有人遇到过? hr = m_pF->QueryInterface(IID_IVRControl, (void **)(&m_...
  • SEH的注册回调函数

    千次阅读 2010-03-28 16:32:00
    所以,如果要自定义一个异常处理程序的话,只要构建一个新的含有ExceptionList字段,将其指向这个结构就可以注册一个SEH异常处理回调函数了。而TIB永远都放在fs段选择器指定的数据段的0偏移处,fs:[0]的地方就是TIB...
  • 本人delphi菜鸟 初接触串口通信 现在程序已经create了串口,注册过一个回调函数了,我现在想要注册另外一个回调函,请问需要重新create一个串口么? 如果方便,留点串口通信的资料更好了 谢谢
  • 原理:定义好处理函数之后,为其定义一个Helper的静态函数,在该静态函数中调用成员函数。pthread_create中绑定的是Helper的静态函数,并传输this指针。 实现: class NDNMib { public:  NDNMib():m_pid(-1)...
  • 使用python向sqlite注册了一个函数函数入参预期是一个整型值,遇到长整型时,发生了溢出,python版本是2.5的,为何会发生长整型溢出呢? import sqlite3 def testInt(para): print "para type is: %s"%type...
  • LUA和C/C++交互-注册回调函数

    千次阅读 2014-10-09 16:37:29
    //lua 脚本注册回调函数 lua_State *L = luaL_newstate();  if (L) { luaopen_base(L); luaL_openlibs(L); lua_register(L, "IsLastTradeDate", LUA_Func::IsLastTradeDate); lua_register...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,721
精华内容 1,488
关键字:

注册回调函数