【问题标题】:Passing member function pointer to the c-style function将成员函数指针传递给 c 风格的函数
【发布时间】:2015-03-22 11:54:15
【问题描述】:

我正在尝试将成员函数指针传递给 c 风格的函数(因为它是 C 中的 lib)

它想要的指针定义为:

void (*)(int, const char*)

所以我要传递的函数是:

void Application::onError(int error, const char *description)

我正在尝试使用此代码传递它:

setCallback(bind(&Game::onError, this, placeholders::_1, placeholders::_2));

这给了我以下错误:

cannot convert ‘std::_Bind_helper<false, void (Application::*)(Application*, int,
const char*), Application* const, const std::_Placeholder<1>&, const 
std::_Placeholder<2>&>::type {aka std::_Bind<std::_Mem_fn<void (Application::*)
(Application*, int, const char*)>(Application*, std::_Placeholder<1>,
std::_Placeholder<2>)>}’ to ‘GLFWerrorfun {aka void (*)(int, const char*)}’ for 
argument ‘1’ to ‘void (* glfwSetErrorCallback(GLFWerrorfun))(int, const char*)’
glfwSetErrorCallback(bind(&Application::onError, this, placeholders::_1, placeholders::_2));

有什么方法可以成功地将成员函数作为绑定函数传递给 c 风格的函数?

【问题讨论】:

    标签: c++ c pointers c++11 callback


    【解决方案1】:

    std::bind 的结果是一个复杂的 C++ 对象。例如,它必须存储所有绑定的参数。所以它绝对不能转换为指向函数的指针。

    您正在处理的回调规范显然不允许“用户数据”有效负载,因此无处隐藏指向可用于调用非静态成员函数的 C++ 对象的指针。这意味着您将不得不调用全局或静态成员函数,或者求助于全局/静态成员/每个线程变量来存储对象指针。

    唯一 100% 可移植的方法是创建一个 C 链接函数用作回调。这样做,并使用一个全局对象指针来调用你原来的onError()

    Application *error_handling_application;
    
    extern "C" void errorCallback(int error, const char *description)
    {
      error_handling_application->onError(error, description);
    }
    

    请注意,您经常会遇到使用静态成员函数代替我的errorCallback 的程序。这适用于大多数平台上的大多数编译器,但不能保证正常工作。 C 库需要一个具有 C 语言链接的函数。静态成员函数只能具有 C++ 语言链接。 C 函数和 C++ 函数的调用机制可能不同(取决于 ABI),这将导致对传入的静态成员函数的错误调用。

    【讨论】:

      【解决方案2】:

      由于成员函数也有 this 指针作为隐含参数,它不是 C 函数接受的类型。因此,恕我直言,唯一的方法是使用 C 链接生成独立函数

      class A {
      public: void func(int, const char*) const;
      };
      
      extern "C" {
        void cfunc(void(*)(int, const char*));
        void call_cfunc(const A*);
      }
      
      // in some source (non-header) file:
      namespace {
        const A*pa;
        void afunc(int i, const char*s)
        { pa->func(i,s); }
      }
      
      void call_cfunc(const A*a)
      {
        pa = a;
        cfunc(afunc);
      }
      

      【讨论】:

      • 赞成,因为它是明智的,并且被反对低于 0。我猜有人反对使用静态变量,因为他们听说这很糟糕,但对此一无所知。
      【解决方案3】:

      不直接,不。 C++ 成员函数需要一个隐式的this 指针,当然C 不知道也不会通过。

      解决这个问题的通常方法是引入“蹦床”作为类方法,但在更现代的 C++ 变体中可能有更漂亮的方法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-08-01
        • 1970-01-01
        • 2021-11-29
        • 2017-05-16
        相关资源
        最近更新 更多