Search code examples
cfunction-pointers

Data Type In C To Represent Any Pointer To Function


Say I have the following definitions for function pointers:

typedef void(*Tmp112HardwareInit)();
typedef void(*Tmp112HardwareDeInit)();
typedef bool(*Tmp112HardwareIsBusy)();

I have an interface object to hold instances of the above function pointers:

typedef struct
{
    Tmp112HardwareInit init;
    Tmp112HardwareDeInit deinit;
    Tmp112HardwareIsBusy is_busy;
} I2CInterface;

static I2CInterface _i2c_interface; // This is declared in module scope

Before accessing these function, I want to check if they've been assigned something. So instead of

_i2c_interface.init();

I want...

if (_i2c_interface.init) _i2c_interface.init();
else error = true;

I don't want to repeat these lines for each access of each variable in _i2c_interface, so I want to write a function:

bool _SensorTMP112_InterfaceInit()
{
    bool success = true;
    if (_i2c_interface.init)
    {
        _i2c_interface.init();
    }
    else
    {
        success = false;
    }

    return success;
}

Now, I don't want to write a function for each of these function pointers in _i2c_interface variable. I want a generic function, which will be called by other functions for each of these function pointers:

// Generic function
bool _SensorTMP112_InterfaceOperation(UnknownType fptr) // What should be UnknownType?
{
    bool success = true;
    if (fptr)
    {
        fptr();
    }
    else
    {
        success = false;
    }

    return success;
}

// Operation specific functions
bool _SensorTMP112_InterfaceInit()
{
    return _SensorTMP112_InterfaceOperation(_i2c_interface.init);
}

bool _SensorTMP112_InterfaceDeInit()
{
    return _SensorTMP112_InterfaceOperation(_i2c_interface.deinit);
}

bool _SensorTMP112_InterfaceIsBusy()
{
    return _SensorTMP112_InterfaceOperation(_i2c_interface.is_busy);
}

My question is what should be the type of UnknownType? Or is it even possible in standard C? Or is there any other way around for what I want to achieve? Not interested in non-standard solutions.


Solution

  • Quick'n'dirty preprocessor macro:

    #define callfn(f) if(f) f(); else result = false
    

    Then

    callfn(_i2c_interface.init);
    result = true;
    callfn(_i2c_interface.deinit);
    

    (when bool success is earlier defined), or use it in functions:

    bool _SensorTMP112_InterfaceInit()
    {
        bool success = true;
        callfn(_i2c_interface.init);
        return success;
    }
    

    (You can also embed the bool success and return success inside the macro as well).

    But you shouldn't expose that macro (i.e. #undef callfn after the functions bodies calling it) because it leaves many open doors.