demote boost::function to a plain function pointer
Has anyone noticed that the accepted answer only works with trivial cases? The only way that function<>::target() will return an object that can be bound to a C callback, is if it was constructed with an object that can be bound to a C callback. If that's the case, then you could have bound it directly and skipped all of the function<> nonsense to begin with.
If you think about it, there isn't any magic solution to this. A C-style callback is stored as a single pointer which points to executable code. Any nontrivial boost::function<> is going to need at least two pointers: one to the executable code, the other to the data that's needed to set up the call (e.g. the 'this' pointer, in the case of a bound member function).
The right way to use boost::function and boost::bind with C callbacks is to create a shim function that satisfies the callback signature, figures out which function<> to call, and calls it. Usually C callbacks will have some kind of a void* for 'user data'; that's where you stash your function pointer:
typedef void (*CallbackType)(int x, void* user_data);
void RegisterCallback(CallbackType cb, void* user_data);
void MyCallback(int x, void* userData) {
boost::function<void(int)> pfn = static_cast<boost::function<void(int)> >(userData);
pfn(x);
}
boost::function<void(int)> fn = boost::bind(myFunction(5));
RegisterCallback(MyCallback, &fn);
Of course, if your callback signature doesn't include some kind of user data pointer, you're out of luck. But any callback that doesn't include a user data pointer is already unusable in most real-world scenarios, and needs to be rewritten.
demote boost::function to a plain function pointer
Has anyone noticed that the accepted answer only works with trivial cases? The only way that function<>::target() will return an object that can be bound to a C callback, is if it was constructed with an object that can be bound to a C callback. If that's the case, then you could have bound it directly and skipped all of the function<> nonsense to begin with.
If you think about it, there isn't any magic solution to this. A C-style callback is stored as a single pointer which points to executable code. Any nontrivial boost::function<> is going to need at least two pointers: one to the executable code, the other to the data that's needed to set up the call (e.g. the 'this' pointer, in the case of a bound member function).
The right way to use boost::function and boost::bind with C callbacks is to create a shim function that satisfies the callback signature, figures out which function<> to call, and calls it. Usually C callbacks will have some kind of a void* for 'user data'; that's where you stash your function pointer:
typedef void (*CallbackType)(int x, void* user_data);
void RegisterCallback(CallbackType cb, void* user_data);
void MyCallback(int x, void* userData) {
boost::function<void(int)> pfn = static_cast<boost::function<void(int)> >(userData);
pfn(x);
}
boost::function<void(int)> fn = boost::bind(myFunction(5));
RegisterCallback(MyCallback, &fn);
Of course, if your callback signature doesn't include some kind of user data pointer, you're out of luck. But any callback that doesn't include a user data pointer is already unusable in most real-world scenarios, and needs to be rewritten.
boost::bind return a function object which is the argument for a function that requires pointer
Traditionally the final void *
argument passed to callbacks is user defined data. If this is the case for you you can create a helper function that will let you pass functors. the only trouble is that you need to ensure that the user data exists until the callback will no longer be called - and that will depend a lot on your program structure. I'm just going to leak the object as thats the easiest way to ensure it continues to exist. ( Though you'll also have problems with the existance of the containing myC
object ).
class myC
{
public:
myA *myOA;
//NOTE: I've removed the void* ptr here, which should be user data.
// If you still need it you'll need to bind it away at functor creation time.
int func(const char * poundVar , char * t1);
int myCCall()
{
//TODO: Fix this intentional leak.
boost::function<int(const char*, char*)> * fn = new boost::function<int(const char*,char*)>( boost::bind(&myC::func,this) );
//Call our helper function instead of `set_pound_func`.
set_pound_func_with_functor(myOA, fn );
return;
}
};
// Function that is really passed to `set_pound_func` when
// set_pound_func_with_functor is called.
// It converts the user data back to a boost function and calls it.
int pound_func_with_functor(const char* d1, char* d2, void* user_data)
{
boost::function<int(const char*,char*)> * fn = static_cast< boost::function<int(const char*, char*) >( user_data );
return (*fn)(d1,d2);
}
//Helper function to make set_pound_func work with boost functions instead.
//NOTE: You are required to ensure the fn argument exists for long enough...
void set_pound_func_with_functor( myA * myOA, boost::function<int(const char *, char *)> & fn )
{
myOA->bridge_set_pound_var_func( £_func_with_functor, &fn );
}
delete boost function while in use
boost::function
or std::tr1::functions
are copyable objects. So, generally there is absolutly no reason to allocate them -- just pass them by value.
They are well optimized for most of real cases... So just pass them by value:
typedef function<int(int)> foo_type;
foo_type global_foo;
int actual_foo( int i, Magic* m )
{
delete global_foo;
return m->magic(i);
}
int main()
{
Magic m;
global_foo = bind( &actual_foo, _1, &m );
return global_foo(10)
}
The code you suggested is dangerous, run this code:
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <iostream>
using namespace std;
boost::function<void()> *glb;
struct Data {
int x;
Data(int _x = 0) : x(_x) { cout<<"ctor:"<<this<<endl; }
~Data() { cout<<"dtor:"<<this<<endl; }
Data(Data const &p) {x=p.x; cout<<"ctor:"<<this<<endl; }
Data const &operator=(Data const &p) { x=p.x; cout<<this<<"="<<&p<<endl; return *this; }
};
void func(Data const &x)
{
delete glb;
cout<<&x<<endl;
}
int main()
{
glb=new boost::function<void()>(boost::bind(func,Data(3)));
(*glb)();
return 0;
}
You would find that you try to access in func
to destoryed object (dtor with same pointer value) that is shown in cout<<&x<<endl
was already called.
Because when you destroy your function objects you also destroy the binded parameters you
have and Data const &x
become unavailible becuase it was destoryed with global_function
Edit: Clearification for comment:
If you have something like
map<string,function<void()> > calls;
void delete_key(){
calls.erase("key");
}
main()
{
calls["key"]=delete_key;
// Wrong and dangerous
// You delete function while in use
calls["key"]();
// Correct and safe
// You create a copy of function so it would not
// be deleted while in use.
function<void()> f=calls["key"];
f();
}
No target() of boost::function of a member function
function::target()
is defined (I'm using the C++11 draft, which I think is a bit more clear than boost's reference) as follows:
per C++0x n3290 20.8.11.2.5[func.wrap.func.targ]/3
Returns: If target_type() == typeid(T) a pointer to the stored function target; otherwise a null pointer.
In your case, T
is your type void(*)(float)
, but Function.target_type()
is not that at all, it is the type of the boost expression used to initialize boost::function.
So in short, yes, this is not allowed. The workarounds are not obvious, but here's one: demote boost::function to a plain function pointer
raw function pointer from a bound method
You can make your own class to do the same thing as the boost bind function. All the class has to do is accept the function type and a pointer to the object that contains the function. For example, this is a void return and void param delegate:
template<typename owner>
class VoidDelegate : public IDelegate
{
public:
VoidDelegate(void (owner::*aFunc)(void), owner* aOwner)
{
mFunction = aFunc;
mOwner = aOwner;
}
~VoidDelegate(void)
{}
void Invoke(void)
{
if(mFunction != 0)
{
(mOwner->*mFunction)();
}
}
private:
void (owner::*mFunction)(void);
owner* mOwner;
};
Usage:
class C
{
void CallMe(void)
{
std::cout << "called";
}
};
int main(int aArgc, char** aArgv)
{
C c;
VoidDelegate<C> delegate(&C::CallMe, &c);
delegate.Invoke();
}
Now, since VoidDelegate<C>
is a type, having a collection of these might not be practical, because what if the list was to contain functions of class B too? It couldn't.
This is where polymorphism comes into play. You can create an interface IDelegate, which has a function Invoke:
class IDelegate
{
virtual ~IDelegate(void) { }
virtual void Invoke(void) = 0;
}
If VoidDelegate<T>
implements IDelegate you could have a collection of IDelegates and therefore have callbacks to methods in different class types.
Related Topics
C++ Obtaining Milliseconds Time on Linux - Clock() Doesn't Seem to Work Properly
How to Concatenate Two Strings in C++
What Does a Colon Following a C++ Constructor Name Do
How to Know the Exact Line of Code Where an Exception Has Been Caused
When to Overload the Comma Operator
C++: Constructor Initializer For Arrays
Difference Between Static, Auto, Global and Local Variable in the Context of C and C++
Convert a Vector≪Int≫ to a String
Sort List Using Stl Sort Function
Dual Emission of Constructor Symbols
Representing 128-Bit Numbers in C++
How to Provide a Swap Function For My Class
How to Detect Win32 Process Creation/Termination in C++
How to Find Memory Leak in a C++ Code/Project
Why Doesn't C++ Support Functions Returning Arrays