Passing member function pointer to the c-style function

前端 未结 3 839
慢半拍i
慢半拍i 2021-01-17 09:52

I am trying to pass member function pointer to the c-style function (as it\'s lib in C)

The pointer it wants is defined as:

void (*)(int, const char*         


        
相关标签:
3条回答
  • 2021-01-17 10:21

    Not directly, no. A C++ member function needs an implicit this pointer, which of course C has no idea about and won't pass.

    The usual way around this is to introduce a "trampoline" as a class method, but perhaps there are prettier ways in more modern C++ variants.

    0 讨论(0)
  • 2021-01-17 10:24

    Since the member function also has the this pointer as implied argument, it is not of the type accepted by the C function. Hence, IMHO the only way is to generate a standalone function with C linkage

    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 讨论(0)
  • 2021-01-17 10:37

    The result of std::bind is a complicated C++ object. It has to store all the bound arguments, for example. So it is most definitely not convertible to a pointer to function.

    The callback specification you're dealing with apparently doesn't allow a "user data" payload, so there's nowhere to hide a pointer to a C++ object which you could use to invoke a non-static member funtion. This means you will have to call a global or static member function, or resort to a global/static member/per-thread variable to store the object pointer.

    The only 100% portable way is to create a C linkage function to use as the callback. This does so, and uses a global object pointer to call your original onError():

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

    Note that quite often, you will encounter programs which use a static member function in place of my errorCallback. This works with most compilers on most platforms, but it is not guaranteed to work. The C library expects a function with C language linkage. A static member function can only have C++ language linkage. It is possible for the calling mechanism of a C function and a C++ function to differ (depends on ABI), which would result in a malformed call to the static member function passed in.

    0 讨论(0)
提交回复
热议问题