【问题标题】:C++ static member function as C callback needs to access non static referenceC++静态成员函数作为C回调需要访问非静态引用
【发布时间】:2014-04-13 21:31:00
【问题描述】:

在我的 C++ 代码中,我依赖于 C 库。这个 C 库让我可以定义一个带有 3 个参数的回调。示例:

文件.c:

#ifdef __cplusplus
extern "C"{
#endif
     typedef void(*callback)(argument* 1, argument* 2, argument* 3);
...
     void set_callback(ARG1, callback name_of_callback);
...

在我正在开发的 C++ 库中,我希望这个回调成为类的成员函数,因为我不能直接将成员函数作为回调传递给 C 库我创建了一个静态函数作为回调并在内部这个静态函数我想引用一个类对象并调用它的成员函数来完成这项工作。

现在我的问题是我的静态函数需要具有 C 库指定的 3 个参数,所以我没有找到一种方法来引用我在该静态函数中开发的类的对象。我想做的例子:

MyClass.h:

class MyClass:
public:
   MyClass();
   void my_function(argument*1, argument* 2, argument* 3);
   static void my_callback(argument* 1, argument* 2, argument*3);

MyClass.cpp:

MyClass::MyClass(){
    set_callback(ARG1, my_callback);
}

void MyClass::my_function(argument*1, argument* 2, argument* 3){ 
      /* Do something */}
void MyClass::my_callback(argument* 1, argument* 2, argument*3){
    Object->my_function(1, 2, 3);
}

不将类成员设置为静态的原因是我希望能够创建和销毁此类的对象以用于测试目的并控制测试中对象的状态。

我正在使用 g++ 和 gcc,希望有人可以提供一些帮助。 提前致谢。

【问题讨论】:

  • 看起来您的set_callback 调用提供了稍后传递给回调的参数之一?通过该参数传递您的MyClass*

标签: c++ c static callback extern


【解决方案1】:

您可以创建一个静态成员函数或纯“C”函数来执行此操作,请考虑以下示例:

/**
 * C++ part
 */
class obj
{
public:
    obj() {}
    ~obj() {}

    void doSomething(int a, int b) { cout << "result = " << a+b << endl; }
};

/**
 * C Part
 */
#ifdef __cplusplus
extern "C"
#endif
{
typedef void (*callback)(void* one, void* two, void* three);

callback g_ptr = NULL;
void* arg = NULL;

void c_lib_core (void)
{
    printf ("C Lib core...\n");
    if (g_ptr)
    {
        g_ptr(arg, NULL, NULL);
    }
}

void set_callback (void* arg, callback ptr)
{
    g_ptr = ptr;
}

void my_callback (void* one, void* two, void* three)
{
    obj* my_obj = (obj*) one;

    my_obj->doSomething(1,2);
}

#ifdef __cplusplus
}
#endif



int main (void)
{
    obj a;

    set_callback (&a, my_callback);

    c_lib_core ();
}

输出:

C Lib core...
result = 3

我将指向 C++ 对象的指针作为参数 1 传递。这允许回调将其转换回 C++ 并调用它。 c_lib_core 的东西只是为了让我可以模拟回调函数的回调以进行测试。这与全局变量一起将在 C 代码中的某处。您只需要实现一个 C 函数并将 ARG1 设置为您的对象即可。

【讨论】:

  • 我使用指向我的对象的全局指针、set_callback 函数和 my_callback 实现了上述解决方案。 set_callback 函数是从类构造函数的 C++ 端调用的。在此解决方案和以下解决方案下,我已经能够通过相同的测试。我只是想知道这个解决方案是否比拥有静态函数和类的静态成员更好?目标是在资源非常有限的微控制器中使用此代码。谢谢
  • 静态成员应该占用与定义一次相同的内存。它们可能是 vtptrs 中的一个条目,但说实话并不确定这一点。如果他们的处理器是如此关注内存,那么纯 C 可能是要走的路,所以你不需要同时包含 C 和 C++ 运行时库,这比这里和那里的几个字节更重要的内存问题
【解决方案2】:

假设没有并发问题,我不知道是否是这种情况,更简单的解决方案可能是定义一个静态实例并在您的静态函数中使用它。

类似的东西。

MyClass.h

class Object;

class MyClass
{
public:
    MyClass();
    static Object* object;
    static void callback();
    ~MyClass();

};

MyClass.cpp

Object* MyClass::object;

MyClass::MyClass()
{
    object = new Object();
}

void MyClass::callback() {
    object->sayHello();
}

MyClass::~MyClass()
{
    delete object;
}

【讨论】:

  • 不将类成员设置为静态的原因是我希望能够创建和销毁此类的对象以用于测试目的并控制测试中对象的状态。
  • 对不起。无论如何,您仍然可以创建和销毁对象并在测试中控制它们的状态。为什么将类成员定义为静态可以防止这种情况发生?
  • 我想确保在 test1 上创建一个 MyClass,其中的成员具有一种状态(p.ex. 对象的 ID=1),并且当事件发生时,回调执行成员函数,在test2 我想创建一个 MyClass,其中成员处于另一个状态(对象的 ID = 5)并且回调执行相同的成员函数。我的印象是,将对象声明为静态会强制对象处于编译时定义的状态。
  • 一点也不。 static 和常量是不同的东西。即,在我的示例中,static 表示每个类只有一个 Object 指针,而不是该类的每个实例。无论是指针还是指向的对象都不是常量,您仍然可以访问它们。您可以,即将ID 传递给MyClass 构造函数,并使用该ID 来实例化新的Object;那么每次创建一个新的MyClass 时,您将拥有一个由object 指向的具有不同ID 的不同对象。
猜你喜欢
  • 1970-01-01
  • 2011-09-30
  • 2023-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-22
  • 2014-04-14
相关资源
最近更新 更多