Trying to integrate plain C/C++ code into iPhone project as an external static library. So far so good, but now I'm stuck at a point, where I need to register library callbacks. The library should notify my iPhone application, when something happens. Seems like a good place to define a Delegate.
...but the library is expecting C function pointers for callbacks. How do I define those in Objective-C, how do I use those as part of delegate pattern?
Sorry, really can't give sample code. Here's something bit similar: first interface I got to use to register, followed by definitions of callbacks.
registerCallBack(&aCBack, &bCBack, &cCBack, &dCBack, &eCBack);
typedef void (aCBack)(uint32_t magic);
typedef void (bCBack)(const NewData* newData);
typedef void (cCBack)(uint32_t value, const std::vector<DataStuff*>* stuff);
typedef void (dCBack)(uint32_t value, const SomeData* data, const std::string text, uint32_t type);
typedef void (eCBack)(uint32_t value, const MoreData* more);
...oh btw, one of the problems is that each Objective-C class method has two hidden arguments. Not sure how to deal with that at all. Besides changing interface of that external library.
You need to use C++/C interfaces for the callbacks which then internally delegate the call to your Objective-C code. Where the callback registrations allow you to pass in user-data of sufficient size, you can conveniently pass something that identifies your context like in this answer.
Callbacks that don't get passed any context have to call a class method of your Objective-C part anyway.
You have to use plain C functions for this, but you can call through to your delegate object from them as long as you're compiling as Objective-C:
// need to have a reference to the object, of course
static DelegateClass* delegate = NULL;
// call at runtime with your actual delegate
void setCallbackDelegate ( DelegateClass* del ) { delegate = del; }
void callbackA ( uint32_t magic )
{
[delegate handleCallbackA:magic];
}
// and so on...
[Update: as gf points out, you can use a class method and avoid the need for setCallbackDelegate.]
Related
I have two types of function pointers defined in my C++ that look like this:
typedef void(*CallbackFn)(bool, std::string, py::array_t<uint8_t>&);
typedef std::function<void(std::string)> LogFunction;
Class Core{
...
void myfunc1(LogFunction lg1, CallbackFn callback, int x, std::string y);
};
and I want to be able to expose them in C but I can't seem to find a way to do so. My first try was to cast these as void* and then recast them back to their actual type. but this seems like a bad idea. So I'm clueless as how to go about this conversion.
Also the solution that I need to come-up with should be doable using C++11 at the very least.
Update:
Thank you very much for your answers. However I need to add a bit more explanation as what I'm after. I know about extern "C" and in fact the C++ functions are exposed using this already in my DLL. However, the problem I had was to pass the function pointers back and forth between the C and C++.
One way was to define function pointers in a way that can be directly usable by C. That is I needed to change for example :
typedef void(*CallbackFn)(bool, std::string, py::array_t<uint8_t>&);
typedef std::function<void(std::string)> LogFunction;
to its C compatible one :
typedef void(*CCallbackFn)(bool, char*, int, unsigned char, int length);
typedef void(*CLogFunction)(char* string, int length);
and use these instead. However, the disadvantage of doing this is that, the DLL is also used by C++ clients and this would be a hindrance to change everything C++ to be compatible by C, I'd lose the advantages of C++ by doing this.
Instead I though of coming up with a second way. The C++ stays the same, but for C linkage and interacting with other languages through C API, I do the conversion myself.
That is they use C style and then I convert this back to C++ in the implementation part. In order to further simplify this so I designed some defaults on C++ part as well. Meaning, suppose for the lack of a better example, the instance needs a callback function to log whatever happens. I define a callback function in case it was not given by the user and create two functions for C API specifically something roughly similar to this:
//in core.cpp for example
include "Core.h"
...
extern "C"
{
Core * core;
...
Core_API void* get_default_log_callback()
{
return (void*) core->SomeDefaultCallback();
}
Core_API void* set_log_callback(void* fn)
{
// convert/cast that to the c++ callback type
// CallbackFn,
core->SetCallback(fn_converted);
}
and the client could for example use the get_default_log_callback and use its return to set_log_call_back.
Basically the idea here is to be able to use the C++ already defined assets.
I was stuck at this conversion process, how to convert such callback pointers to a C compatible type ( like what I showed, it'd be really easy to just cast the pointer to void* for example and write a C wrapper that accepts void* and then recast it to the proper type.
I'd like to know about this scenario as well and whether this is a good practice or the otherwise a bad one.
Question two:
Also I'd like to know if it is possible to have a conversion from for example the CCallbackFn and CallbackFn?
Suppose I've got a function(my C function above e.g.) in a CCalbackFn form ,but I want to ultimately have it in CallbackFn form(change it and call the underlying C++ that accepts CallbackFn) ? is this possible ?
C doesn't do / cannot handle C++ name mangling (nor C++ types that are not identical to C types). You cannot use non-POD types (and plain function pointers involving types not usable in C) in anything exposed to C. And you need to use extern "C" for the exposed stuff, to disable name mangling (or rather, use whatever naming convention/mangling your current platforms C compiler uses).
In short: use extern "C" for anything that must be callable from C and make sure anything exposed that way only uses types that you can write/use in C.
You can expose a function to C by declaring it extern "C".
However, the function must only accept argument types that are valid in C.
From the look of the code above, you're going to have to express your callback in more C-like terms.
In order to expose any C++ functions to C, you should wrap the C++ calls in C functions in a plain C++ library. And export only the C functions from it. Use a common header for C functions declarations inside and outside the library. These functions will be callable from any C environment. All the C++ types wrap in a class and pass a pointer to that class across function wrappers, as a handle to C++ environment. The pointer to class should be void* or just long. And only in C++ side you will reinterpret it to own environment class.
Update 1:
You should keep C and C++ separated. It means don't do conversions between C and C++. Keep separated C versions and C++ versions of XX_log_callback functions. For instance your C++ functions uses std::string, py::array_t&. There is no way you can use it is C. No conversion available, and no way to take advantages of it in C. You can take advantage of C++ only in C++, so make a separate version for C++ only and one available for C developers.
This is a by the way. There is a technique of passing around C++ interfaces to C and back to C++. But be attentive, it uses only C compatible return and argument types. It means creating a structure with a pointer to a table of function pointers. In C++ it is an interface but in C it is a struct. This technique is used in COM/OLE2 in Windows. https://www.codeproject.com/Articles/13601/COM-in-plain-C To use such a technique you should understand very well how to make a C++ class compatible with a C struct.
Now I will just copy/paste some pieces of code from the codeproject with little explanations.
The rule of thumb when passing interfaces between C and C++, use only types compatible with C as function arguments and as return type. The first four bytes in the interface is a pointer to an array of functions, called Virtual Table:
typedef struct
{
IExampleVtbl * lpVtbl;//<-- here is the pointer to virtual table
DWORD count;//<-- here the current class data starts
char buffer[80];
} IExample;
Here you add the pointers to functions in the virtual table. The IExampleVtbl is a structure filled with pointers, and binary it is equivalent to a contiguous array of pointers
static const IExampleVtbl IExample_Vtbl = {SetString, GetString};
IExample * example;
// Allocate the class
example = (IExample *)malloc(sizeof(IExample));
example->lpVtbl = &IExample_Vtbl;//<-- here you pass the pointer to virtual functions
example->count = 1; //<-- initialize class members
example->buffer[0] = 0;
Now this is how you call the methods:
char buffer[80];
example->lpVtbl->SetString(example, "Some text");
example->lpVtbl->GetString(example, buffer, sizeof(buffer));
Keep in mind, all of above is C.
In the above example you refer explicitly the virtual table member, and also you pass it explicitly as first parameter in the functions. The C++ equivalent of call to GetString/SetString is:
example->SetString("Some text");
example->GetString(buffer, sizeof(buffer));
Here is the SetString/GetStrinf functions and the virtual table structure:
HRESULT STDMETHODCALLTYPE SetString(IExample *this, char * str)
{
memcpy(this->buffer, str, length);//be attentive, it is almost pseudocode
return(0);
}
HRESULT STDMETHODCALLTYPE GetString(IExample *this, char *buffer, int buffer_len)
{
memcpy(str, this->buffer, length);//be attentive, it is almost pseudocode
return(0);
}
typedef struct {
SetStringPtr *SetString;
GetStringPtr *GetString;
} IExampleVtbl;
The STDMETHODCALLTYPE is to make it compatible with C++ calling of member function classes, so you will be able to pass the IExample between C and C++. I believe this will be really a nightmare for the C programmers, but not an easy task for C++ counterparts.
To access that when interface is passed from C, you declare interface like this:
class IExample
{
public:
virtual HRESULT SetString(char * str) = 0;//<-- see first parameter gone away in both functions
virtual HRESULT GetString(char *buffer, int buffer_len) = 0;
};
If you implement in C++ to pass in C equivalent of above code will be:
class IExample
{
int count = 1; //<-- initialize class members
char buffer[80] = "";
public:
virtual HRESULT SetString(char * str)
{
memcpy(this->buffer, str, length);//be attentive, it is almost pseudocode
return(0);
}
virtual HRESULT GetString(char *buffer, int buffer_len)
{
memcpy(str, this->buffer, length);//be attentive, it is almost pseudocode
return(0);
}
};
One more thing. You don't use the C declaration in C++ and vice-versa. This is by the COM approach to address the issue. It might be not portable to different compilers but keep in mind, similar approach is done in the old CORBA. Only you should keep in mind. You create one interface for C and one for C++. On C++ part hide the C interface and on C hide the C++ interface. Pass around only the pointers.
I ultimately came up with my own solution which I myself refer to as "Delegating Callbacks" approach! The idea here is that, instead of directly use the C callback, you create a diversion, you create an intermediate callback that acts as a translator between the two APIs.
For example, suppose my C++ class has a method that accepts only callbacks with this signature :
typedef void(*CallbackFn)(bool, std::string, py::array_t<uint8_t>&);
And now we want to expose this to C. and this is our C callback signature :
typedef void(*CCallbackFn)(bool, const char*, unsigned char*, int rows, int cols);
Now how do we go from the first to the second one or vice versa? We create a new callback in our C++ class of type CallbackFn, and inside it execute the C callbacks. So using an indirect call, we can easily decouple the signatures between the C and C++ APIs and use the ones that are most suitable for each.
To make it more concrete we need to have something like this:
CORE_API void Core::DelegateCCallback(bool status, std::string id, py::array_t<uint8_t>& img)
{
//here is used a std::map to store my c-callbacks you can use
//vector or anything else that you like
for (auto item: this->callbackMap_c)
{
//item.first is our callback, so use it like a function
item.first(status, id.c_str(), img.mutable_data(), img.shape(0), img.shape(1));
}
}
And you update your C callback list like this, using two exposed functions, Add and Remove to add and remove any callbacks respectively :
extern "C"
{
//Core is our C++ class for example
Core* core = nullptr;
...
CORE_API void AddCallback(CCallbackFn callback)
{
core->AddCallback_C(callback);
}
CORE_API void RemoveCallback(CCallbackFn callback)
{
core->RemoveCallback_C(callback);
}
}
and back in our C++ class, AddCallback_C methods are defined like:
CORE_API void Core::AddCallback_C(CCallbackFn callback)
{
auto x = this->callbackMap_c.emplace(callback, typeid(callback).name());
}
CORE_API void Core::RemoveCallback_C(CCallbackFn callback)
{
this->callbackMap_c.erase(callback);
}
Just adding/removing the callback to the callback list. That's all.
Now when we instantiate our C++ Code, we need to add the DelegateCCallback to the callback list, so when all C++ callbacks are executed this one executes too and with it, it will loop through all the C callbacks and executes them one by one.
For example in my case, the callbacks needed to be run in a Python module, so in my constructor I had to do something like this:
CORE_API Core::Core(LogFunction logInfo)
{
//....
// add our 'Callback delegate' to the list of callbacks
// that would run.
callbackPyList.attr("append")(py::cpp_function([this](bool status, std::string id, py::array_t<uint8_t>& img)
{
this->DelegateCCallback(status, id, img);
}));
//...
}
You can get fancy with this and incorporate threads, etc as you wish.
I'd like to expose ObjC notification handlers to my C++ client code.
I'm doing it this way.
I wrapped an ObjC object (call it X) inside a C++ object.
X observes the notification and registers a callback (call it F).
F translates the ObjC structures from the notification into their C++ counterparts, calls a user-registered global C++ callback function (call it FF). The translated C++ structs become the input arguments of FF.
Now the problem is that the arguments' original ObjC structures are complex, containing multiple layers of ObjC objects that need to be translated.
On my side, the wrapper observer F needs to do nothing special, just calling the client's FF.
What is the more proper strategy of my translation at this point?
Should I:
Translate those structures down to the bottom-level of all their members so that I have equivalent C++ structures to use as the arguments, or,
Create a C++ class to wrap these arguments into one object and expose the class interface to user so they can use those C++-wrapped arguments in their C++ implementation, or,
Give up on the wrapping idea and ask user to code in ObjC and register their own observer functions directly?
My targeted users are iOS developers that may or may not be Android developers too.
You can mix c++ and objective-c++ in a .mm implementation file. This means you can give a c++ lambda (or block) to the objective-c++ class that references your c++ owner.
something like this:
implementation.mm:
#interface Shim : NSObject
{
std::function<void>() _notify;
}
#end
#implementation Shim
- void register_cpp(std::function<void>() f)
{
_notify = std::move(f);
}
- (void) my_handler()
{
if(_notify)
_notify();
}
#end
struct cpp_class::impl {
impl()
: _shim([Shim alloc[init]])
{
_shim.register_cpp(std::bind(&impl::callback, this));
}
private:
void callback() {
// do callback here;
}
Shim* _shim;
};
cpp_class::cpp_class()
: _impl(new impl)
{
}
cpp_class::~cpp_class()
{
delete _impl;
}
header.h:
struct cpp_class{
cpp_class();
~cpp_class();
private:
struct impl;
impl* _impl;
};
In reality you'll want to be careful to ensure that objects still exist when doing callbacks (argues for weak_ptr::lock(), enable_shared_from_this, etc.) since objective-c likes to put callbacks onto a thread's run loop (basically a queue) and that means your c++ object can go away before the callback arrives - but this code should give you the right idea.
I'm a newbie to arduino and programming.
I've included a library inside my own library in arduino, but first library contains a function which has a pointer function as a parameter. It is an interrupt service routine(ISR) but I need to call a function in my cpp file when interrupt is occurred. So I need to pass the pointer of that function to the first library code. It works well when I use it in .ino file, I can pass it like,
attachInterrupt(functionISR_name);
but when I use it in .cpp file, I get errors. my function is like,
void velocity::functionISR_name(){
//some code
}
but how can I pass the pointer of this function to the first library function? I tried this way but got errors,
attachInterrupt(velocity::functionISR_name);
You cannot pass a method to a function which expects a function, unless you define it static.
write it static :
static void velocity::functionISR_name()
and
attachInterrupt(&velocity::functionISR_name);
Unfortunately the static method is not bound to a specific instance any more. You should use it only together with a singleton. On Arduino you should write the class like shown below in the code snipped:
class velocity
{
static velocity *pThisSingelton;
public:
velocity()
{
pThisSingelton=this;
}
static void functionISR_name()
{
pThisSingelton->CallWhatEverMethodYouNeeded();
// Do whatever needed.
}
// … Your methods
};
velocity *velocity::pThisSingelton;
velocity YourOneAndOnlyInstanceOfThisClass;
void setup()
{
attachInterrupt(&velocity::functionISR_name);
// …other stuff…
}
This looks ugly, but in my opinion it is totally okay with Arduino as the opportunities are very limited on such a system.
Thinking again over it, I would personal go for the approach Sorin mentioned in his answer above. That would be more like that:
class velocity
{
public:
velocity()
{
}
static void functionISR_name()
{
// Do whatever needed.
}
// … Your methods
};
velocity YourOneAndOnlyInstanceOfThisClass;
void functionISR_name_delegation()
{
YourOneAndOnlyInstanceOfThisClass.functionISR_name();
}
void setup()
{
attachInterrupt(functionISR_name_delegation);
// …other stuff…
}
It would also save you some bytes for the pointer you need in the first example.
As a site note: For the future, please post the exact code (for e.g. attachInterrupt needs more parameter) and copy&paste the error messages. Usually error are exact at a place you do not suspect. This question was an exception. Normally I and other would ask for better specification.
You pass a pointer to the function but the function is a class member. Likely the call will be invalid because the this pointer will be garbage(may compile fine but will throw strange errors at runtime).
You need to define a plain vanilla function, outside of any class, and use that.
If you don't have a very complex project you can get away with having a global pointer to the class instance you should use and just delegate the call in your new function.
If you want to do thing the right way you need some mechanism to get the instance pointer I talked about above. Usually this involves either a singleton or some factory pattern.
Example:
class Foo {
void method() {
x = 5;
}
int x;
}
Having a callback on method will crash because you have an invalid pointer for this so x=5 will write 5 somewhere randomly in memory.
What you need is somehting like:
static Foo* foo_instance; // Initialized somewhere else.
void method_delegator() {
foo_instance->method();
}
Now you can pass method_delegator to the function. It will work because you now also pass foo_instance for this pointer.
I got stuck. I am trying to form a function that will eat classless function pointers and ones from objects. Here is my current code that hopefully explains more.
(It should run on a Arduino, so I cannot use big libraries.)
First off, I am using this library for the Arduino:
/* SimpleTimer - A timer library for Arduino.
* Author: mromani#ottotecnica.com
* Copyright (c) 2010 OTTOTECNICA Italy
*/
Which takes functions which it calls on a set timer interval of this type:
typedef void (*timer_callback)(void);
As far as my knowledge goes, it's a classles function, the webpage Pointers to member functions got me really far but, not far enough. Probably a terminology deficit on my side.
Now, I have made my own class which I would like in turn to use this SimpleTimer library. But if I feed the SimpleTimer my class functions, it does not like them (what I understand). But how would it be possible to make this happen without altering the SimpleTimer library.
So there is the class Robot, which has Robot::halt(). I want the robot to move forward for a set amount of time. Like so:
void Robot::forward(int speed, long time) {
reset();
timer.setTimer(time, c_func, 1);
analogWrite(l_a, speed);
analogWrite(r_a, speed);
isMoving(true);
}
void Robot::halt() {
__isMoving = false;
digitalWrite(r_a, LOW);
digitalWrite(r_b, LOW);
digitalWrite(l_b, LOW);
digitalWrite(l_a, LOW);
}
The c_func variable is a classless function at this point, but I would like to use the Robot::halt function. I have looked, read, learned but haven't succeeded yet. I just can't seem to wrap my head around this one because I am missing some angle.
I tried:
timer.setTimer(time, (this->*halt), 1);
timer.setTimer(time, Robot::*halt, 1);
timer.setTimer(time, &Robot::halt), 1);
But it would all amount to the same problem/ me just stabbing in the dark here...
EDIT
Earlier, I said not wanting to change the SimpleTimer library code. I want to comeback on this one, I guess altering it there would be the better option.
Thanks for all the current answers already, I was only allowed to flag one as a viable answer, actually everyhting I read here was extremely helpful.
To continue this, changing the SimpleTimer code. This class needs to have a reference to the object that holds my "halt" function, right? So, overloading the settimer function to something that takes my object and my function as two seperate pointers would work...? I think I am getting the hang of this but, I am not there yet with my head.
EDIT
I don't know who came with this one again but, anyone finding this thread. If found Member Function Pointers and the Fastest Possible C++ Delegates to give a very nice introduction in function pointers and member function pointers.
EDIT
Got it working, changed the SimpleTimer library to use this Delegate system:
http://www.codeproject.com/KB/cpp/FastDelegate.aspx
It integrated very nicely, and it could be nice to have a standard Delegate system like this in the Arduino library.
Code as in test (working)
typedef
typedef FastDelegate0<> FuncDelegate;
Code in robot class:
void Robot::test(){
FuncDelegate f_delegate;
f_delegate = MakeDelegate(this, &Robot::halt);
timer.setTimerDelg(1, f_delegate, 1);
}
void Robot::halt() {
Serial.println("TEST");
}
Code in SimpleTimer class:
int SimpleTimer::setTimerDelg(long d, FuncDelegate f, int n){
f();
}
Arduino prints TEST in the console.
Next step putting it in an array, don't see a lot of problems there. Thanks everyone, I can't believe the stuff I learned in two days.
What's that smell? Is that the smell of...? Success!
For the ones interested, the used Delegate system does not amount to memory capacity issues:
With FastDelegate
AVR Memory Usage
----------------
Device: atmega2560
Program: 17178 bytes (6.6% Full)
(.text + .data + .bootloader)
Data: 1292 bytes (15.8% Full)
(.data + .bss + .noinit)
Finished building: sizedummy
Without FastDelegate:
AVR Memory Usage
----------------
Device: atmega2560
Program: 17030 bytes (6.5% Full)
(.text + .data + .bootloader)
Data: 1292 bytes (15.8% Full)
(.data + .bss + .noinit)
Finished building: sizedummy
You can do this by making a functor object, that acts as a proxy between the timer code and your code.
class MyHaltStruct
{
public:
MyHaltStruct(Robot &robot)
: m_robot(robot)
{ }
void operator()()
{ robot.halt(); }
private:
Robot &m_robot;
}
// ...
timer.setTimer(time, MyHaltStruct(*this), 1);
Edit
If it can't be done via a functor object, you could global variables and functions instead, maybe in a namespace:
namespace my_robot_halter
{
Robot *robot = 0;
void halt()
{
if (robot)
robot->halt();
}
}
// ...
my_robot_halter::robot = this;
timer.setTimer(time, my_robot_halter::halt, 1);
This only works if you have one robot instance though.
Since the timer callback signature doesn't take any argument, you unfortunately need to use some global (or static) state:
Robot *global_robot_for_timer;
void robot_halt_callback()
{
global_robot_for_timer->halt();
}
you can at least wrap that lot into it's own file, but it isn't pretty. As Matthew Murdoch suggested, it might be better to edit the SimpleTimer itself. A more conventional interface would be:
typedef void (*timer_callback)(void *);
SimpleTimer::setTimer(long time, timer_callback f, void *data);
void robot_halt_callback(void *data)
{
Robot *r = (Robot *)data;
r->halt();
}
ie, when you call setTimer, you provide an argument which is passed back to the callback.
The smallest change to SimpleTimer would be something like:
SimpleTimer.h
typedef void (*timer_function)(void *);
struct timer_callback {
timer_function func;
void *arg;
};
// ... every method taking a callback should look like this:
int SimpleTimer::setTimeout(long, timer_function, void *);
SimpleTimer.cpp
// ... callbacks is now an array of structures
callbacks[i] = {0};
// ... findFirstFreeSlot
if (callbacks[i].func == 0) {
// ... SimpleTimer::setTimer can take the timer_callback structure, but
// that means it's callers have to construct it ...
int SimpleTimer::setTimeout(long d, timer_function func, void *arg) {
timer_callback cb = {func, arg};
return setTimer(d, cb, RUN_ONCE);
}
You can't pass a non-static member function there - only a static one. The signature should be like this:
static void halt()
{
//implementation
}
the reason is that each non-static member function has an implicit Robot* parameter known as this pointer which facilitates access to the current object. Since the callback signature doesn't have such Robot* parameter you can't possibly pass a member function of class Robot unless it is static.
So that in your implementation
void halt();
is in effect
static void halt( Robot* thisPointer );
and when you do
void Robot::halt() {
__isMoving = false;
}
you effectively have this:
void Robot::halt( Robot* thisPointer ) {
thisPointer->__isMoving = false;
}
and of course a halt( Robot*) function pointer can't be passed in place of void (*)(void) C callback function.
And yes, if you need access to non-static member variables of class Robot from inside the callback you'll have to somehow retrieve the pointer to class Robot instance elsewhere - for example, store it as a static member variable so that you don't rely on this pointer.
It's important to understand that function pointers and pointers to class members are different not for an arbitrary reason but the fact that instance methods have an implicit this argument (also, they have to work with inherited and virtual functions, which adds even more complexity; hence they can be 16 or more bytes in size). In other words, a function pointer to a class member is only meaningful together with an instance of the class.
As the currently-top answer says, your best bet is to go with functors. While the setTimer function might only accept function pointers, it is possible to write a template function to wrap the call and accept both. For even more fine-grained processing, you can write a template metaprogram (Boost.TypeTraits has is_pointer, is_function and even is_member_function_pointer) to handle the different cases.
How you make the functors is a different story. You can opt for writing them by hand (which means implementing a class with operator() for each one of them), but depending on your needs that might be tedious. A couple of options:
std::bind: you can use it to create a functor whose first parameter will be bound to the value you specify - in the case of member functions, it will be the instance.
Depending on your compiler, you might not have access to std::bind - in this case I suggest boost::bind. It is a header-only library and provides the same functionality.
You can use another delegate implementation. I don't have experience with this one, but claims to be faster than other implementations (including std::function).
The mentioned libraries are header-only, so they probably don't count as "big libraries".
Suppose I have some code like this:
class Visitor {
public:
Visitor(callBackFunction) {}
void visit() {
//do something useful
invokeCallback();
}
}
class ClassThatCanBeVisited {
Visitor &visitor;
public:
ClassThatCanBeVisited(Visitor &_visitor) : visitor(_visitor){}
void someUsefulMethod() {
int data= 42;
visitor.visit(data);
}
};
void callBackFunction() {
//do something useful in the context of the Main file
}
int main() {
Visitor visitor;
ClassThatCanBeVisited foo(visitor);
foo.someUsefulMethod();
}
I need to create a simple callback that will be called whenever the Visitor::visit() is called. I know that I probably should put the code of the callback inside my Visitor, but it is in a different context, so I would like to pass the callBackFunction() to the Visitor so he could invoke my callback function.
I looked for things on the web and saw boost::function, but c++ already has the basic functors.
Which one should I use for better clarity of the code? The callback is going to be a simple void() function, but it might grow, you never know the future :)
What is the recommended way to do this?
Yes boost::function would do this well. That's a very common usage of it. You will need to use boost::bind to bind the instance to the member function.
func = boost::bind( &MyClass::CallbackFunc, this);
Would be how you would do that from within the class.
Be sure the "this" doesn't dissapear or your boost function will crash in the middle of some boost header somewhere.
You can use callback interface and its hierarchy if you don't want to use boost::function.
class VisitorCallback
{
public:
virtual void handle( const Visitor& ) = 0;
};
If you have or can use boost::function - use it, it is a good way to get rid of all those callback classes.
Edit:
#edisongustavo:
boost::function and boost::bind won't probably make your code more readable. But it will give you an opportunity to pass free functions ( I mean functions out of class and static class functions ) as callback as well as existing functions of any class.
With boost functions you can pass functions with for example 2 parameters as callback which expect only one parameter.
typedef boost::function< void ( int ) > IntExpectingCallback;
void TwoIntFunction( int, int );
{
}
...
IntExpectingCallback callback = boost::bind( TwoIntFunction, 5, _1 );
But again, this won't make your code more readable unless all your team knows and favor boost.
The above answers are great, but I'd just like to point out something you mentioned in your question, which is still relevant to your choice between C++ callback objects (in Mykola's answer) and boost.
"the callback is going to be a simple void() function, but it might grow, you never know the future :)"
This is probably the worst reason to extra, unnecessary functionality - that is "just in case you need it". If you don't know - then don't do more than is necessary, chances are your guess will be wrong anyway, especially by the time you need it.
On the other hand, if you do know that it is extremely likely you will need the functionality very soon, then it might be worth adding it.
Again to re-iterate what Mykola said - if you already have boost in your project and your team likes it, then use that, but otherwise it may be overkill.