将成员函数传递给需要回调的C接口

时间:2016-02-29 15:23:58

标签: c++ c std

我有一个带有普通C接口的旧.dll,它会在完成某些工作时调用回调。它所采用的回调类型为void (f*)(char* arg)

我正在寻找一种技巧来传递一个C ++函数对象,以便调用回调,并将“this”指针存储在某处,类似于bind,但是简单绑定不起作用

为了说明这一点:C接口:

typedef void (f*)(char* param) Callback;
void registerCallback(Callback c);

C ++中的用法:

class A
{
    void func1()
    {
         registerCallback(std::bind(&A::func2, _1, this)); // obviously doens't work
    }

    void func2(char* param)
    { ... }
};

4 个答案:

答案 0 :(得分:3)

使用我所知道的类的实例和类的成员函数来实现此功能的唯一方法是:

  1. 存储指向全局变量中对象的指针。
  2. 注册非会员功能。
  3. 使用全局变量从非成员函数调用成员函数。
  4. withErrors()

答案 1 :(得分:1)

我看到它的方式,问题的核心是让回调函数的调用者(实体registerCallback正在注册)知道要调用哪个A对象的func2

根据您的问题我可以理解,您基本上有一堆A个对象,并且您只需要许多这些A个对象来执行各自的func2时发生回调事件。但是,回调事件发生时,回调函数的调用者不知道调用谁。既然你提到它是一个旧的.dll,我认为我们不能只是进入并改变registerCallback的工作方式,但我们需要存储注册回调的A个对象。

因此,

class Informer {
public:
  static void InformAllMembers(char* param) {
    for(auto& a : m_Members) { //Inform all As registered with me
      a->func2(param);
    }
  }
  static void Register(A* a) {
    m_Members.push_back(a);
  }
private:
  static std::vector<A*> m_Members;
};
std::vector<A*> Informer::m_Members;
...

registerCallback(Informer::InformAllMembers);

A a;
Informer::Register(&a);

注意:您必须处理销毁某些已注册A个对象并从Informer取消注册的情况。

答案 2 :(得分:0)

这只是使用A类中的静态成员的@ RSahu解决方案的替代方案。恕我直言,在功能上与全局变量相同,但至少在你的类中得到命名空间包含:

class A
{
    static A* current_obj;

public:    
    void func1()
    {
         current_obj = this;
         registerCallback(func3);
    }

private:
    void func2(char* param)
    { ... }
    static void func3(char *param) {
        if (NULL == current_obj) {
            // error ...
        }
        current_obj->func2(param);
    }
...
};

如上所示,已注册的函数可以是类的私有函数,因为需要在外部调用的唯一函数是func1

但是它遇到了同样的问题:你只能同时注册一个对象。

答案 3 :(得分:0)

也许我不理解这个问题,但为什么不建立一个简单的包装来保持&#34;这个&#34;指针。因此,应用程序将使用此回调(或lambda)

void RegisterCallback_withthis(char* arg, void* thisptr)

一次只能向DLL注册一个回调函数。因此,单个全球性的theptr是好的。

static void* thisptr;
void RegisterCallback(char* arg)
{
     RegisterCallback_withthis(argc, thisptr);
}

应用程序必须在注册回调时设置thisptr。

thisptr = this;