C++ Using Class Method as a Function Pointer Type

后端 未结 3 507
庸人自扰
庸人自扰 2020-11-29 11:53

In a C lib, there is a function waiting a function pointer such that:

lasvm_kcache_t* lasvm_kcache_create(lasvm_kernel_t kernelfunc, void *closure)
         


        
3条回答
  •  温柔的废话
    2020-11-29 12:19

    I'm assuming that the closure argument is a context 'cookie' for the use of the callback to get appropriate context. This is a acomon idiom for callback functions, and seems to be what's going on based on the snippets you've provided (but I don't know for sure, as I don't know anything about kcache_create() except what you posted here).

    You can use that cookie to pass a pointer to the cls_lasvm instance you're dealing with like so:

    extern "C"
    double
    lasvm_kcache_create_callback( int i, int j, void* closure)
    {
        // have to get a cls_lasvm pointer somehow, maybe the 
        // void* clpsure is a context value that can hold the
        // this pointer - I don't know
    
        cls_lasvm* me = reinterpret_cast( closure);
    
        return me->kernel( i, j)
    
    }
    
    
    class cls_lasvm //...
    {
    
        ...
    
        // the callback that's in the class doens't need kparam
        double cls_lasvm::kernel(int i, int j);
    
    };
    
    ...
    
    // called like so, assuming it's being called from a cls_lasvm
    //  member function
    
    lasvm_kcache_t *kcache=lasvm_kcache_create(&lasvm_kcache_create_callback, this);
    

    If I'm wrong about closure being a context cookie, then your callback function in the cls_lasvm class needs to be static:

    extern "C"
    double
    lasvm_kcache_create_callback( int i, int j, void* closure)
    {
        // if there is no context provided (or needed) then
        // all you need is a static function in cls_lasvm
    
        return cls_lasvm::kernel( i, j, closure);
    }
    
    // the callback that's in the class needs to be static
    static double cls_lasvm::kernel(int i, int j, void* closure);
    

    Note that a C callback function implemented in C++ must be extern "C". It may seem to work as a static function in a class because class-static functions often use the same calling convention as a C function. However, doing that is a bug waiting to happen (see comments below), so please don't - go through an extern "C" wrapper instead.

    If closure isn't a context cookie and for some reason cls_lasvm::kernel() can't be static then you need to come up with a way to stash a this pointer somewhere and retrieve that pointer in the lasvm_kcache_create_callback() function, similar to the way I did in my first example, except that pointer has to come dfrom some mechanism you devise yourself. Note that this will likely make using lasvm_kcache_create() non-reentrant and non-threadsafe. That may or may not be a problem depending on your specific circumstances.

提交回复
热议问题