I am trying to interface with a library written in c, that uses this familiar pattern:
void some_c_handler(void(*func)(void*), void* data);
Now, I want to write a C++ wrapper for this function that looks like this:
void my_new_cpp_handler(std::function<void()>&& func)
{
void (*p)() = foo(func);
void* data = bar(func);
some_c_handler(p, data);
}
Both some_c_handler and my_new_cpp_handler are solving the same problem; they're taking in some kind of function along with some state. But the latter is preferred in that it abstracts much of the implementation details from the user, and allows for simply passing in a lambda object.
So my_new_cpp_handler should take the func parameter it is given, convert it to a function pointer and pass its state on to data.
I don't know enough about the standard, or the implementation of std::function to know if this is even a reasonable request. Can foo and bar exist?
To put it differently, what I want is to be able to pass a stateful function to a c callback handler without having to manually instantiate my own struct type to pass along with it. Obviously std::function has already done this for us, so I'd love to be able to separate the function pointer from the state somehow and pass it onto the c-style handler. Is this possible?
Is this possible?
No.
You can wrap a C-style callback into an std::function<>..., and the compiler will emit code to extract the data and the handler and call it. However, the exact code to do so will depend on the compiler, the ABI and the standard C++ library being used. You can't magically reconstruct that code given only the std::function wrapper.
Further, an arbitrary std::function... (or a lambda) may wrap code other than a call to C-style handler. It should be obvious that applying the "magically reconstructed" code to extract C-style handler from such an instance of std::function... can't possibly succeed.
P.S.
To put it differently, what I want is to be able to pass a stateful function to a c callback handler without having to manually instantiate my own struct type to pass along with it. Obviously std::function has already done this for us
So why don't you just use what std::function has already done for you:
void my_new_cpp_handler(std::function<void()>&& func)
{
func(); // calls some_c_handler(p, data) IFF that is what "func" encodes.
}
If you were to carefully review the documentation for this library, you will find that the
void some_c_handler(void(*func)(void*), void* data);
Invokes func, passing it the data argument.
This is a very common design pattern for C libraries that take a callback function. In addition to the callback function, they also take an additional opaque pointer that is not interpreted by the library, but is blindly forwarded to the func. In other words, the C library invokes
func(data);
You can use this from C++ code to pass an ordinary pointer to any class.
This includes std::function, too.
The trick is that in most situations it will be necessary to use new:
auto *pointer=new std::function< function_type >...
The end result is a pointer that can be passed to the C library, together with a pointer to a "trampoline function":
some_c_handler(&cpp_trampoline, reinterpret_cast<void *>(pointer));
And the trampoline recasts the opaque pointer:
void cpp_trampoline(void *pointer)
{
auto real_pointer=reinterpret_cast<std::function< ... >*>(pointer);
// At this point, you have a pointer to the std::function here.
// Do with it as you wish.
The only detail you will need to square away here is to figure out the correct scope for the dynamically-allocated function pointer, in order to avoid memory leaks.
You can make a wrapper function whose purpose is to simply execute the std::function callback.
void some_c_handler(void(*)(void*), void*) {}
void std_function_caller(void* fn) {
(*static_cast<std::function<void()>*>(fn))();
};
auto make_std_function_caller(std::function<void()>& fn) {
return std::make_pair(std_function_caller, static_cast<void*>(&fn));
}
void my_new_cpp_handler(std::function<void()>&& func) {
const auto p = make_std_function_caller(func);
some_c_handler(p.first, p.second);
}
According to this link, the std::function object has no accessible member that can provide raw access to the pointer. You should probably define a struct that contains a pointer to the function pointer and the object, and a constructor wrapper that stores the pointer's address to the struct before the construction of your std::struct, so as to assign the address stored in the pointer it points to to your C handler's parameter.
Related
I am trying to interface with a library written in c, that uses this familiar pattern:
void some_c_handler(void(*func)(void*), void* data);
Now, I want to write a C++ wrapper for this function that looks like this:
void my_new_cpp_handler(std::function<void()>&& func)
{
void (*p)() = foo(func);
void* data = bar(func);
some_c_handler(p, data);
}
Both some_c_handler and my_new_cpp_handler are solving the same problem; they're taking in some kind of function along with some state. But the latter is preferred in that it abstracts much of the implementation details from the user, and allows for simply passing in a lambda object.
So my_new_cpp_handler should take the func parameter it is given, convert it to a function pointer and pass its state on to data.
I don't know enough about the standard, or the implementation of std::function to know if this is even a reasonable request. Can foo and bar exist?
To put it differently, what I want is to be able to pass a stateful function to a c callback handler without having to manually instantiate my own struct type to pass along with it. Obviously std::function has already done this for us, so I'd love to be able to separate the function pointer from the state somehow and pass it onto the c-style handler. Is this possible?
Is this possible?
No.
You can wrap a C-style callback into an std::function<>..., and the compiler will emit code to extract the data and the handler and call it. However, the exact code to do so will depend on the compiler, the ABI and the standard C++ library being used. You can't magically reconstruct that code given only the std::function wrapper.
Further, an arbitrary std::function... (or a lambda) may wrap code other than a call to C-style handler. It should be obvious that applying the "magically reconstructed" code to extract C-style handler from such an instance of std::function... can't possibly succeed.
P.S.
To put it differently, what I want is to be able to pass a stateful function to a c callback handler without having to manually instantiate my own struct type to pass along with it. Obviously std::function has already done this for us
So why don't you just use what std::function has already done for you:
void my_new_cpp_handler(std::function<void()>&& func)
{
func(); // calls some_c_handler(p, data) IFF that is what "func" encodes.
}
If you were to carefully review the documentation for this library, you will find that the
void some_c_handler(void(*func)(void*), void* data);
Invokes func, passing it the data argument.
This is a very common design pattern for C libraries that take a callback function. In addition to the callback function, they also take an additional opaque pointer that is not interpreted by the library, but is blindly forwarded to the func. In other words, the C library invokes
func(data);
You can use this from C++ code to pass an ordinary pointer to any class.
This includes std::function, too.
The trick is that in most situations it will be necessary to use new:
auto *pointer=new std::function< function_type >...
The end result is a pointer that can be passed to the C library, together with a pointer to a "trampoline function":
some_c_handler(&cpp_trampoline, reinterpret_cast<void *>(pointer));
And the trampoline recasts the opaque pointer:
void cpp_trampoline(void *pointer)
{
auto real_pointer=reinterpret_cast<std::function< ... >*>(pointer);
// At this point, you have a pointer to the std::function here.
// Do with it as you wish.
The only detail you will need to square away here is to figure out the correct scope for the dynamically-allocated function pointer, in order to avoid memory leaks.
You can make a wrapper function whose purpose is to simply execute the std::function callback.
void some_c_handler(void(*)(void*), void*) {}
void std_function_caller(void* fn) {
(*static_cast<std::function<void()>*>(fn))();
};
auto make_std_function_caller(std::function<void()>& fn) {
return std::make_pair(std_function_caller, static_cast<void*>(&fn));
}
void my_new_cpp_handler(std::function<void()>&& func) {
const auto p = make_std_function_caller(func);
some_c_handler(p.first, p.second);
}
According to this link, the std::function object has no accessible member that can provide raw access to the pointer. You should probably define a struct that contains a pointer to the function pointer and the object, and a constructor wrapper that stores the pointer's address to the struct before the construction of your std::struct, so as to assign the address stored in the pointer it points to to your C handler's parameter.
Imagine the following scenario:
typedef std::function<float(float)> A;
typedef float(*B)(float);
A foo();
void bar(B b);
You wish to do something along the lines of:
bar(foo());
Obviously this does not work. Mainly because A can contain a state and B is a function pointer. What if we know that A does not contain a state and we wish to somehow take it's "meaning" and put it into something that can be passed for a B?
Is it impossible?
If you can ensure that the callable object stored in A is a function pointer or a lambda with an empty capture list, you can simply get a function pointer in this way:
foo().target<B>();
In general, a std::function can "box" some closure (e.g. the value of some lambda function). And a closure contains both code and data (the closed values). So I believe that you cannot portably convert it to a naked function pointer. BTW, because conceptually closures are mixing code and data languages not providing them (like C) practically requires callbacks (i.e. the convention to pass every function pointer with some additional data, look into GTK for a concrete example).
Some implementation specific tricks might make a trampoline function on the stack (e.g. dynamically generate, perhaps with asmjit, some machine code containing a pointer to the closure, etc.). But this is not portable and system specific (in particular because the stack needs to be executable)
What if we know that A does not contain a state and we wish to somehow take it's "meaning" and put it into something that can be passed for a B?
Even that isn't sufficient. std::function provides a target() member function, that if you know the exact type of the underlying functor, you can get it back. So we can do, for instance:
void print(int i) { std::cout << i; }
std::function<void(int)> f = print;
auto ptr = f.target<void(*)(int)>(); // not null
(*ptr)(42); // works
However, even if our functor f doesn't contain state, that doesn't mean that its underlying type is precisely void(*)(int). It could be a completely different function pointer, in which case we wouldn't be able to pull it out:
int square(int i) { return i*i; }
f = square;
ptr = f.target<void(*)(int)>(); // nullptr!
Or it could be a lambda, in which case we wouldn't even be able to name the type, much less pull it out:
f = [](int i){ std::cout << i; }; // same as print, right?
ptr = f.target<void(*)(int)>(); // ... nope :'(
Basically, type erasure is really type erasure. If you need the original underlying type, that's likely indicative of a bad design.
I have hot two classes. Assume that one of them is an Image and the other is a Page. The Image object receives an OnPointerPressed event and When it happens I would like to call a function form the Page calss. The problem is that this function is not defined until I pass the address of the member function to the image using union hack. When this method is called from the Image class it works fine but inside the method I can't see the Page Object and its members.
MainPage::MainPage(void)
{
//.......
image1->OnPointerPressedHandler->add(&MainPage::imageMousePressed);
}
void MainPage::imageMousePressed(STObject* sender, STPointerEventArg * args)
{
void * dsda = this; //the address of this is something wierd
pres = true;
}
Can anybody help a little?
template<class T>
void add(T const & x)
{
union hlp_t{
void * v_ptr;
T t;
};
hlp_t a;
a.t = x;
functions->addLast(a.v_ptr);
}
template<class ARG>
void trigger(SENDERTYPE sender, ARG arg)
{
STLinkedListIterator<void *>* it = functions->createIteator();
if(it != nullptr)
{
do
{
void (*callback)(SENDERTYPE,ARG) =static_cast<void (*)(SENDERTYPE,ARG)>(it->getData());
callback(sender,arg);
/*
void * myVoid = it->getData();
__asm
{
push [arg];
push [sender];
call [myVoid];
}
*/
it->next();
}while(!it->EOL());
}
}
In both the assembly language version and the non-assembly language version of your code you are calling the member function incorrectly. There are specific requirements for member functions that do not apply to calling a free function (and static member functions) which is exactly what both versions of your code are doing. When calling non-static member functions the this pointer is implicitly passed as the first parameter. This can be done by either pushing the pointer value onto the stack, placing it in a register, or both - it really depends on how the compiler generates the calling code.
The current version of your code attempts to call the member function as if it was a free function but passes the object pointer on the stack. This is a very bad idea and is the reason why the value of this is incorrect. It also may not work as you expect if ARG is an object being passed by value instead of by reference or pointer. This is because the entire object needs to be copied onto the stack - don't even try doing this yourself. Instead you should use the features provided by the language that are specifically intended to allow you to call member functions by pointer.
The syntax for a pointer to member function is returntype (ClassType::*)(parameters). By using the correct syntax you can rely on the compiler to tell you when you use it incorrectly instead of trying to hunt down obscure bugs like you are currently doing. Not only should you use this when calling the member function but you should use it to store the pointer in your list. VC++ allows you to convert a function pointer to a void pointer but this is a Microsoft extension to the language and is not standard C++. I recommend you avoid the void whenever possible.
The one change you will need to make is how you are calling the member function. This is different than using a pointer to a free function and the following shows the correct syntax.
(objectpointer->*functionpointer)(arguments);
The extra set of parenthesis is required due to operator precedence and the ->* is the "pointer to member" operator. The code below shows the changes you will need to make to your code to correctly call the member function.
template<class ARG>
void trigger(STObject* sender, ARG arg)
{
STLinkedListIterator<void *>* it = functions->createIteator();
if(it != nullptr)
{
do
{
// cast to a pointer to member function so the compiler knows
// the correct type of the function call.
void (STObject::*callback)(ARG)
= static_cast<void (STObject::*)(ARG)>(it->getData());
// call it using the correct syntax and let the compiler
// handle all the gory details.
(sender->*callback)(arg);
it->next();
}while(!it->EOL());
}
}
You can make this more generic by adding an additional template parameter to specify the type of the target object.
template<class SENDER, class ARG>
void trigger(SENDER* sender, ARG arg)
{
STLinkedListIterator<void *>* it = functions->createIteator();
if(it != nullptr)
{
do
{
void (SENDER::*callback)(ARG)
= static_cast<void (SENDER::*)(ARG)>(it->getData());
(sender->*callback)(arg);
it->next();
}while(!it->EOL());
}
}
.
As a side note the function add() contains undefined behavior. From $9.5/1 of the C++ Language Standard
In a union, at most one of the data members can be active at any time, that is, the value of at most one of the data members can be stored in a union at any time.
In add() you set the value of t then read the value of v_ptr.
You need to pass in the 'this' pointer as well to make this work, otherwise it would instantiate a separate instance of the class:
You have to modify the imageMousePressed like this:
// add in a void* argument
void MainPage::imageMousePressed(STObject* sender, STPointerEventArg * args, void* mainPageObject)
{
MainPage* dsda = (MainPage*) mainPageObject; // now, you should have a pointer to the valid object
pres = true;
}
Now, this would mean the add function of OnPointerPressedHandler should also be modified to accomodate this:
image1->OnPointerPressedHandler->add(&MainPage::imageMousePressed, this);
And internally it should pass call the pointed function passing the 'this' value. The reason this does not work now, if the function is instantiated like a static function which would then be a part of a new object, so the state of your old object would not be preserved.
PS: You should paste more code to give a better idea to folks who answer this
Can I use boost::bind(mycallback, this, _1, _2) across C code?
Update
The short answer is no, boost bind does not return a function pointer, which can be called in C code, but a functor (C++ object with overloaded () operator) see answer below.
The best way to do what you want to do is to create a C callback that then calls the boost::function, which is stored in some sort of user memory with new.
Example:
void callFunction(void* data)
{
boost::function<void(void)> *func = (boost::function<void(void)>* ) (data);
(*func)();
delete(func);
}
Then you simply pass this callback and set the user data(however it is specified in libev) to be a copy of your function allocated with new.
This is how you specify user data with libev:
http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#ASSOCIATING_CUSTOM_DATA_WITH_A_WATCH
No. boost::bind returns a Functor not a function pointer. The returned object is a C++ object which has an overloaded operator() which allows it to behave like a function pointer in C++ code. But it is not a function pointer which can be passed into C code.
I assume you want to use whatever boost::bind returns as a callback function for a C library?
If that's the case, then no, it won't work. It won't even build, as boost::bind does not return a function pointer.
This is probably a philosophical question, but I ran into the following problem:
If you define an std::function, and you don't initialize it correctly, your application will crash, like this:
typedef std::function<void(void)> MyFunctionType;
MyFunctionType myFunction;
myFunction();
If the function is passed as an argument, like this:
void DoSomething (MyFunctionType myFunction)
{
myFunction();
}
Then, of course, it also crashes. This means that I am forced to add checking code like this:
void DoSomething (MyFunctionType myFunction)
{
if (!myFunction) return;
myFunction();
}
Requiring these checks gives me a flash-back to the old C days, where you also had to check all pointer arguments explicitly:
void DoSomething (Car *car, Person *person)
{
if (!car) return; // In real applications, this would be an assert of course
if (!person) return; // In real applications, this would be an assert of course
...
}
Luckily, we can use references in C++, which prevents me from writing these checks (assuming that the caller didn't pass the contents of a nullptr to the function:
void DoSomething (Car &car, Person &person)
{
// I can assume that car and person are valid
}
So, why do std::function instances have a default constructor? Without default constructor you wouldn't have to add checks, just like for other, normal arguments of a function.
And in those 'rare' cases where you want to pass an 'optional' std::function, you can still pass a pointer to it (or use boost::optional).
True, but this is also true for other types. E.g. if I want my class to have an optional Person, then I make my data member a Person-pointer. Why not do the same for std::functions? What is so special about std::function that it can have an 'invalid' state?
It does not have an "invalid" state. It is no more invalid than this:
std::vector<int> aVector;
aVector[0] = 5;
What you have is an empty function, just like aVector is an empty vector. The object is in a very well-defined state: the state of not having data.
Now, let's consider your "pointer to function" suggestion:
void CallbackRegistrar(..., std::function<void()> *pFunc);
How do you have to call that? Well, here's one thing you cannot do:
void CallbackFunc();
CallbackRegistrar(..., CallbackFunc);
That's not allowed because CallbackFunc is a function, while the parameter type is a std::function<void()>*. Those two are not convertible, so the compiler will complain. So in order to do the call, you have to do this:
void CallbackFunc();
CallbackRegistrar(..., new std::function<void()>(CallbackFunc));
You have just introduced new into the picture. You have allocated a resource; who is going to be responsible for it? CallbackRegistrar? Obviously, you might want to use some kind of smart pointer, so you clutter the interface even more with:
void CallbackRegistrar(..., std::shared_ptr<std::function<void()>> pFunc);
That's a lot of API annoyance and cruft, just to pass a function around. The simplest way to avoid this is to allow std::function to be empty. Just like we allow std::vector to be empty. Just like we allow std::string to be empty. Just like we allow std::shared_ptr to be empty. And so on.
To put it simply: std::function contains a function. It is a holder for a callable type. Therefore, there is the possibility that it contains no callable type.
Actually, your application should not crash.
ยง 20.8.11.1 Class bad_function_call [func.wrap.badcall]
1/ An exception of type bad_function_call is thrown by function::operator() (20.8.11.2.4) when the function wrapper object has no target.
The behavior is perfectly specified.
One of the most common use cases for std::function is to register callbacks, to be called when certain conditions are met. Allowing for uninitialized instances makes it possible to register callbacks only when needed, otherwise you would be forced to always pass at least some sort of no-op function.
The answer is probably historical: std::function is meant as a replacement for function pointers, and function pointers had the capability to be NULL. So, when you want to offer easy compatibility to function pointers, you need to offer an invalid state.
The identifiable invalid state is not really necessary since, as you mentioned, boost::optional does that job just fine. So I'd say that std::function's are just there for the sake of history.
There are cases where you cannot initialize everything at construction (for example, when a parameter depends on the effect on another construction that in turn depends on the effect on the first ...).
In this cases, you have necessarily to break the loop, admitting an identifiable invalid state to be corrected later.
So you construct the first as "null", construct the second element, and reassign the first.
You can, actually, avoid checks, if -where a function is used- you grant that inside the constructor of the object that embeds it, you will always return after a valid reassignment.
In the same way that you can add a nullstate to a functor type that doesn't have one, you can wrap a functor with a class that does not admit a nullstate. The former requires adding state, the latter does not require new state (only a restriction). Thus, while i don't know the rationale of the std::function design, it supports the most lean & mean usage, no matter what you want.
Cheers & hth.,
You just use std::function for callbacks, you can use a simple template helper function that forwards its arguments to the handler if it is not empty:
template <typename Callback, typename... Ts>
void SendNotification(const Callback & callback, Ts&&... vs)
{
if (callback)
{
callback(std::forward<Ts>(vs)...);
}
}
And use it in the following way:
std::function<void(int, double>> myHandler;
...
SendNotification(myHandler, 42, 3.15);