First, you need to declare a pointer type to hold the address of your callback. The basic definition of a function is a bit odd in c++. There is a further complication that in C++ we have functions, function-objects, and template types.
The standard provides a basic function template type:std::function. This type
holds not a function pointer, but a callable object.
#include <functional>
To declare a specific function type, pass its signature to std::function as its template parameter.
typedef std::function<int(const char*)> StdFreeFunc;
// you can also define types for member functions, and define
// member function pointers this way
struct A{};
typedef std::function<int A::*(const char*)> StdMemberFunc;
// member callable objects are called with this syntax:
// (obj.*callable)(args); or (obj->*callable)(args);
// the parenthesis are often required to keep the compiler happy
// A callable object:
struct CallMe
{
int xy;
int operator()(const char*) { /*...*/ return xy; }
};
std::function is compatible with function objects, lambdas and regular function pointers (see below). Works best with C++ only stuff.
struct AStruct
{
StdFreeFunc callback_; // we hold a value, not a pointer
void setCallback(StdFreeFunc&& cb) // pass by value, reference, const ref,
{ // move... like any object type
callback_ = cb;
};
int callCallback(const char* str)
{
if (callback_) // callable object has a bool() operator to check if valid !!
return (callback_)(str);
// the parenthesis and is optional, so this is the same:
if (callback_)
return callback_(str):
}
};
// example with callable object:
AStruct as, ar;
as.setCallback(CallMe{42}); // we can pass an object with data
ar.setCallback(CallMe{84}); // to obtain different effects
as.callCallback("prints fourty two");
ar.callCallback("prints eighty four");
C-style function pointers
Before C++, there was C. THis is how it's done in C, and it does compile. The disadvantage with C-style function pointers is that they are not compatible with function objects. On the other hand they are compatible with C, and many other languages such as PASCAL, VB, etc..
For example, the type a function taking a const char* as a parameter and returning an int is written as:
typedef int (CallBack)(const char*);
The most usual form is to declare a pointer, since that's what is stored. As in:
typedef int (*CallBack)(const char*);
// you can specify extra call specifications
typedef int (__stdcall * CallBack)(const char*); // uses PASCAL calling
// exmample:
struct YourStruct
{
//...
Callback callback_{nullptr}; // this is a pointer initialize to nullptr
//...
void setCallback(Callback cb)
{
// call as ys.setCallback(AFunction)
// or ys.setCallback(&AFunction)
callback_ = cb;
};
int callCallback(const char* str)
{
if (callback_) // always check if valid !!
return (*callback_)(str);
// the parenthesis and the * are optional, so this is the same:
if (callback_)
return callback_(str):
}
};
int UserFunction(const char*) { /*...*/ return 0; }
YourStruct ys;
ys.setCallback(&UserFunction);
ys.callCallback("hello");