美文网首页
C函数回调(callback)C++类成员函数的方法

C函数回调(callback)C++类成员函数的方法

作者: 多宝鱼丁 | 来源:发表于2017-12-30 11:01 被阅读0次

问题的由来

C回调的步骤一般是:

  1. 声明callback函数类型;
  2. 根据类型定义一个callback函数A;
  3. 把定义的函数A,作为参数传入到另外一个函数B;
  4. 函数B会在某个时刻,调用A。

因为C里面函数定义了之后,都是一个全局变量,编译就会分配好地址,所以可以很方便的传递和使用。

但是在C++里,情况有点不一样:
C++的类成员方法即使声明定义了,如果这个类不实例化成对象,那么,类成员方法是不会有地址的,所以也就无法传递给C函数。
简单讲,就是你不能使用一个尚且还不存在东东~
那怎么办呢?


问题的解决

经过摸索,目前总结有两种方法:

一. 类成员函数声明成static函数

类的static成员讲解请看这篇:C++ 类的静态成员详细讲解
声明成static的类成员函数,简单讲,就跟C语言的全局函数是一个意思,编译阶段就确定好了内存地址,不再依赖对象而存在,因此使用起来就跟C函数是一样的,只不过要这样:类名::方法(),要加个前缀。

在VC下的代码如下:
mythread.h

#ifndef _MY_TEST_H_
#define _MY_TEST_H_

class TestClass {
public:
    TestClass();
    ~TestClass();

    static void notify(int arg1, int arg2);     // declared as static function

private:
    void callback();
};

#endif

mythread.cpp:

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>

#include "mythread.h"

typedef void * HANDLE;

#define SEMAPHORE HANDLE
#define THREADHANDLE HANDLE
#define THREADPROCESS DWORD WINAPI
#define THREADRETURN 0
#define PTHREADPROCESS LPTHREAD_START_ROUTINE
#define NULLTHREAD NULL

int g_thread_end = 0;

TestClass::TestClass() {

}

TestClass::~TestClass() {

}

void TestClass::notify(int arg1, int arg2) {
    printf("notify() is called!\n");
    //callback();                              // static function cannot call no-static function 
}

void TestClass::callback() {
    printf("callback() is called!\n");
}


THREADHANDLE os_creatthread(PTHREADPROCESS fun,void *para)
{
    unsigned long id;
    return CreateThread(NULL,0,fun,para,0,&id);
}

void waitforthread()
{
    while (g_thread_end == 0)
    {
        NULL;
    }   
}

typedef void(*testCb)(int arg1, int arg2);

THREADPROCESS threadfun(PVOID arg)
{
    int i;
    testCb mC;
        
    mC = (testCb)arg;

    for(i=0; i < 50; i++)
    {
        printf("%02d: ", i);
        mC(0, 0);                                   // callback is called!
        Sleep(500);
    }
 
    g_thread_end = 1;
    return 0;
}

void main()
{
    THREADHANDLE pthread = NULLTHREAD;

    printf("Creating thread...\n");
    pthread = os_creatthread(threadfun, TestClass::notify);     // new a thread and register callback
    printf("Creating thread completed.Handle:%x\n", pthread);
    
    printf("Waiting for thread...\n");
    waitforthread();
    
    printf("Waiting ended.\n");

}

注释应该写的很清楚了:)
要注意的一点是:

  • 静态函数是无法访问类的非静态成员的

二. 传递对象

基于一切皆对象的观点,既然不能直接传函数,那我们就传对象好了嘛~
请看代码:
mythread.h:

#ifndef _MY_TEST_H_
#define _MY_TEST_H_

class TestClass {
public:
    TestClass();
    ~TestClass();

    void notify();

private:
    void callback();
};

#endif

mythread.cpp:

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>

#include "mythread.h"

typedef void * HANDLE;

#define SEMAPHORE HANDLE
#define THREADHANDLE HANDLE
#define THREADPROCESS DWORD WINAPI
#define THREADRETURN 0
#define PTHREADPROCESS LPTHREAD_START_ROUTINE
#define NULLTHREAD NULL

int g_thread_end = 0;

TestClass::TestClass() {

}

TestClass::~TestClass() {

}

void TestClass::notify() {
    printf("notify() is called! -> ");
    callback();
}

void TestClass::callback() {
    printf("callback() is called!\n");
}


THREADHANDLE os_creatthread(PTHREADPROCESS fun,void *para)
{
    unsigned long id;
    return CreateThread(NULL,0,fun,para,0,&id);
}

void waitforthread()
{
    while (g_thread_end == 0)
    {
        NULL;
    }   
}

THREADPROCESS threadfun(PVOID arg)
{
    int i;
    TestClass *mC;
        
    mC = (TestClass *)arg;

    for(i=0; i < 50; i++)
    {
        printf("%02d: ", i);
        mC->notify();                                       // callback function is calling
        Sleep(500);
    }
 
    g_thread_end = 1;
    return 0;
}

void main()
{
    THREADHANDLE pthread = NULLTHREAD;

    TestClass *myClass = new TestClass();                   // firstly, new an object

    printf("Creating thread...\n");
    pthread = os_creatthread(threadfun, myClass);           // register this object as callback
    printf("Creating thread completed.Handle:%x\n", pthread);
    
    printf("Waiting for thread...\n");
    waitforthread();
    
    printf("Waiting ended.\n");

    delete myClass;
}

OK,说完了,两种方法哪种更好用,我目前还挺喜欢第二种的,因为没有只能访问静态成员的限制,有了对象之后,你就可以为所欲为啦~

相关文章

网友评论

      本文标题:C函数回调(callback)C++类成员函数的方法

      本文链接:https://www.haomeiwen.com/subject/vtuggxtx.html