如何从 C 回调中修改 C++ class 成员变量

How to modify C++ class member variables from C callback

我的目标是改变 TTerm 中的 WidthHeight

#include <iostream>

extern "C" 
{
    void SomeCFunctionThatRequireCallback(void (*FuncPtr)(int Width, int Height))
    {
        FuncPtr(80, 20);
    }
}

class TTerm
{
public:
    int IO;
    int WinchFds[2];

    int Width;
    int Height;

    TTerm()
    {
        SomeCFunctionThatRequireCallback(OnResizeCallback);
    }

    static void OnResizeCallback(int Width, int Height)
    {
        // Set this->Width and this->Height
    }
};

int main() 
{
    TTerm Term;
}

如果 C 回调是你的或者你可以改变它,你可以传递一个指向 class 实例的指针并在静态方法中调用一些成员函数:

extern "C" 
{
    void SomeCFunctionThatRequireCallback(void * ptr, void (*FuncPtr)(void *, int, int))
    {
        FuncPtr(ptr, 80, 20);
    }
}

    TTerm()
    {
        SomeCFunctionThatRequireCallback(this, OnResizeCallback);
    }

    static void OnResizeCallback(void * ptr, int Width, int Height)
    {
        // Set this->Width and this->Height
        TTerm * instance = (TTerm*)ptr;
        instance->Width = Width;
        instance->Heght = Height;
    }

您也可以将整数作为引用传递。但是,同样,您需要修改回调签名。

如果无法更改回调签名,则必须控制谁调用回调并在静态方法中执行某些操作。

您可以在另一个 class 中使用信号量保护回调并从那里获取所需的数据。

(非编译示例。)

TTerm() {
    SomeCFunctionObject & obj = SomeCFunctionObject.getInstance();
    obj.setCaller (this);
    obj.doCallback ();
    Width = obj._width;
    Height = obj._height;
}

class SomeCFunctionObject {
public:
    int _width;
    int _height;

    static SomeCFunctionObject & getInstance () {
        static SomeCFunctionObject obj;
        return obj;
    }

    static void OnResizeCallback(int Width, int Height)
    {
        SomeCFunctionObject & obj = SomeCFunctionObject.getInstance();
        obj._width = Width;
        obj._height = Height;
        // free semaphore
    }    
    void setCaller (void * using) {
        // get semaphore
        _using = using
    }

    void doCallback () {
        SomeCFunctionThatRequireCallback(OnResizeCallback);
    }

private:
    void * _using;

    SomeCFunctionObject () {}

};