Saving function pointer+arguments for later use - c++

I have this problem where a C++ function pointer is saved, together with a set of arguments to call it on, such that it can be called later. The calling code is unaware of the type and arguments of the functions. Saving and calling function pointers and arguments is extremely performance critical in my application. The interface should look something like this:
void func( int a, char * b );
call_this_later( func, 5, "abc" );
A straightforward solution is to put all of this information in a functor, requiring a different typedef per called function. C++11 would allow me to do that using a variadic template, so that is ok.
Since the type of the functor is not known at the point of call, it seems necessary to create a virtual base class for these functors and to invoke the functors using virtual function calls. The performance overhead of virtual function calls + heap allocation is too high (I am pushing the boundaries of implementing this idiom with as few assembly instructions as possible). So I need a different solution.
Any ideas?

You could do this with a lambda expression which captures the types.
template <typename Func, typename Arg1, typename Arg2>
std::function<void(void)> call_this_later(Func f, Arg1 a1, Arg2 a2) {
return [=]() { f(a1, a2); }; // Capture arguments by value
}
A few things to note:
I don't think you can use perfect forwarding here since you have to capture the arguments
Since C++ is not garbage collected, if the arguments are pointers they may point to something that isn't alive later on. For example if your argument is const char* then it's OK if you use it with a string literal but not if you pass someStdString.c_str() and the string is going to die any-time soon.
I gave the example with two arguments, if your compiler supports variadic templates you can use those otherwise just create an overload for each number of arguments.

What about a solution using boost::function / boost::bind:
void func( int a, char * b );
boost::function<void ()> my_proc =
boost::bind(&func, 5, "abc");
// then later...
my_proc(); // calls func(5, "abc");

You're going to need a custom allocator to match your allocation pattern. Alternatively, use compile-time polymorphism to pass the type of the functor in to the call site.

Related

Is it possible for C++ to implement function pointers point to different parameter lists?

I recently wrote about the function of class member function callbacks. I need to save the callback object and function pointer, then call the function pointer and fill in the appropriate parameters where the callback is needed.
I started out as a form of typedef void (AAA::*Function)(int a, int b);, but when I need to support different parameter lists of member function, I obviously need a dynamic way to implement it.
class AAA
{
public:
int add(int a, int b)
{
return (a + b);
}
};
class BBB
{
public:
void setValue(std::string value)
{
this->value = value;
}
private:
std::string value;
};
class CCC
{
public:
void bind(??? p) // Binding objects and callback functions.
{
this->p = p;
}
template <class... Args>
auto callback(Args&&... args) // Autofill parameter list.
{
return this->p(std::forward<Args>(args)...);
}
private:
??? p; // How is this function pointer implemented?
};
int main()
{
AAA aaa;
BBB bbb;
CCC ccc;
ccc.bind(???(aaa, &AAA::add));
int number = ccc.callback(5, 6);
ccc.bind(???(bbb, &BBB::setValue));
ccc.callback("Hello");
system("pause");
return 0;
}
I don't know how can I implement the function pointer "???".
You basically are asking to have fully dynamicly typed and checked function calls.
To have fully dynamic function calls, you basically have to throw out the C++ function call system.
This is a bad idea, but I'll tell you how to do it.
A dynamicly callable object looks roughly like this:
using dynamic_function = std::function< std::any( std::vector<std::any> ) >
where use use
struct nothing_t {};
when we want to return void.
Then you write machinery that takes an object and a specific signature, and wraps it up.
template<class R, class...Args, class F>
struct dynamic_function_maker {
template<std::size_t...Is>
dynamic_function operator()(std::index_sequence<Is...>, F&& f)const {
return [f=std::forward<F>(f)](std::vector<std::any> args)->std::any {
if (sizeof...(Is) != args.size())
throw std::invalid_argument("Wrong number of arguments");
if constexpr( std::is_same< std::invoke_result_t<F const&, Args... >, void >{} )
{
f( std::any_cast<Args>(args[Is])... );
return nothing_t{};
}
else
{
return f( std::any_cast<Args>(args[Is])... );
}
};
}
dynamic_function operator()(F&& f)const {
return (*this)(std::make_index_sequence<sizeof...(Args)>{}, std::forward<F>(f));
}
};
template<class R, class...Args, class F>
dynamic_function make_dynamic_function(F f){
return dynamic_function_maker<R,Args...,F>{}(std::forward<F>(f));
}
next you'll want to deduce signatures of function pointers and the like:
template<class R, class...Args>
dynamic_function make_dynamic_function(R(*f)(Args...)){
return dynamic_function_maker<R,Args...,F>{}(std::forward<F>(f));
}
template<class Tclass R, class...Args>
dynamic_function make_dynamic_function(T* t, R(T::*f)(Args...)){
return dynamic_function_maker<R,Args...,F>{}(
[t,f](auto&&...args)->decltype(auto){return (t->*f)(decltype(args)(args)...);}
);
}
then after fixing typos above you should be able to solve your original problem.
Again, as someone who can actually write and understand the above code, I strongly advise you not to use it. It is fragile and dangerous.
There is almost never a good reason to store callbacks in places where you don't know what the arguments you are going to call it with.
There should be a different type and instance of CCC for each set of arguments you want to call it with. 99/100 times when people ask this question, they are asking the wrong question.
C++ is a type-safe language. This means that you cannot do exactly what you've outlined in your question. A pointer to a function that takes specific parameters is a different type from a pointer to a function that takes different parameters. This is fundamental to C++.
std::bind can be use to type-erase different types to the same type, but you get a single type at the end, that can be called only with a matching set of parameters (if any). It is not possible to invoke the "underlying" bound function, with its real parameters. That's because the whole purpose of std::bind is to make them disappear, and inaccessible. That's what std::bind is for.
You only have a limited set options to make this work while staying with the bounds and constraints of C++'s type-safety.
Make use of a void *, in some fashion. Actually, don't. Don't do that. That will just cause more problems, and headache.
Have a separate list and classes of callbacks, one list for each set of callbacks that take a specific set of parameters. You must know, at the point of invoking a callback, what parameters you intend to pass. So, just get your callback from the appropriate list.
Make use of std::variant. The type-safe std::variant is C++17 only (but boost has a similar template that's mostly equivalent, and available with older C++ revisions). All your callbacks take a single std::variant parameter, a variant of every possible set of parameters (designated as a std::tuple of them, or some class/struct instance). Each callback will have to decide what to do if it receives a std::variant containing the wrong parameter value.
Alternatively, the std::variant can be a variant of different std::function types, thus shifting the responsibility of type-checking to the caller, instead of each callback.
The bottom line is that C++ is fundamentally a type-safe language; and this is precisely one of the reasons why one would choose to use C++ instead of a different language that does not have the same kind of type-safety.
But being a type-safe language, that means that you have certain limitations when it comes to juggling different types together. Specifically: you can't. Everything in C++ is always, and must be, a single type.

Calling a stateless lambda without an instance (only type)

I'm trying to write a wrapper for a "register callback" type of interface from a C library. The issue is quite complicated by the fact that, the library lets you register "variadic" functions by accepting a list of parameter definitions. Then at callback time, the function is expected to extract its arguments from a type-erased list of arguments. Good old C...
The interface I'm trying to create is to accept any function, even a lambda, and automatically generate all the machinery to correctly register this function, along with registering the arguments and extracting them during callback time. So the user should only have to type:
register_callback("Callback Name", [](int i){return i+0.5;});
Now this is theoretically possible, but at one point, I need to be able to call the lambda without any instance, but with access to only its type. I don't understand why, but the default constructor of a stateless (non-capturing) lambda is deleted, so I can't simply default-construct from its type. What I'm planning to do instead is a very dirty-looking, but should probably be OK way to work around this:
template <class Func, class RET, class ...ARGS>
struct from_stateless {
static RET to_function(ARGS...args) {
RET (*f)(ARGS...) = *(Func *)(0);
return f(args...);
}
};
so that from_stateless<LAMBDA_TYPE, RET, ARGS...>::to_function is actually a function pointer that I can call without an argument and more importantly one that I can pass as a TEMPLATE ARGUMENT.
Under normal circumstances, the line RET (*f)(ARGS...) = *(Func *)(0); would be suicide, but it really should be safe with this use case, isn't it? After all, the function pointer obtained after conversion couldn't in any universe possibly depend on the lambda instance.
So, the question is, is it safe to do this as long as I make sure that the type is indeed a stateless lambda? Or am I missing something? Note that the RET (*f)(ARGS...) = *(Func *)(0); would trigger a compiler error if a closure accidentally slips through.
CLARIFICATION: I can't just decay the lambda to a function pointer and register it, since the signature of the lambda is not compatible with the "Register" method. The register method expects a function with signature: void (*)(int number_of_args, TypeErasedValue * arguments, TypeErasedValue * result) So you see, I need to (and already do), through template metaprograming, generate a free function templated on the type of the lambda to act as an adaptor between the expected and the actual signatures.
It gets even easier than #Yakk's answer if you take advantage of the fact that a lambda can see the static locals of its enclosing scope without needing to capture them. Using this fact you can wrap the user-provided stateless lambda in your own stateless lambda with the required signature, and convert the latter into a function pointer.
using callback = void (*)(int, TypeErasedValue*, TypeErasedValue*);
template <typename F>
callback stateless_to_callback(F f) {
static F static_f = f;
return [](int argc, TypeErasedValue* argv, TypeErasedValue* result) {
// extract arguments from argv
auto r = static_f( /* arguments... */ );
// store r in result
};
}
Want defined behaviour?
Add:
static Func state(Func* op=0){
static Func f=*op;
return f;
}
to your template class. First time you call it, pass a ptr to lambda. 2nd time, extract value for free.
The static Func f is constructed the first time the function is called: so long as the pointer is non-null that time, we are good. Every other time it is called, the pointer can be null and it does not use it, as static locals are only constructed once.
Call it to 'register' with pointer to lambda. Elsewhere (at callback), call it to get a copy. Lambda is stateless, so copy is free.
Assuming you have something to register normal function
template <typename Ret, typename... Args>
void register_callback(const std::string& s, Ret(*)(Args...))
{
std::cout << "register function " << s << std::endl;
// Implementation
}
You may simply explicitly convert your non-capturing lambda in pointer on function:
template <typename Lambda>
void register_callback(const std::string& s, const Lambda&f)
{
// convert non capturing lambda into function pointer
Register(s, +f);
}
Live demo
or change your call site to something like:
register_callback("Callback Name", +[](int i){return i + 0.5;});
Note: You may use * instead of + for the decay.

Is it possible to store variadic arguments into a member variable?

I want to know if it is possible to store variadic template arguments into a member variable, for example a tuple? So I can use it in another method. I want it to work something like this, see below:
class TempClass
{
public:
//How can I Store the arguments with the help of a variable?
std::tuple<Template Args?> savedArgs;
template<typename ...Args>
void SaveTheseArgs(args&& ...args)
{
//Store the arguments into a variable for later use
savedArgs = std::make_tuple<Args>(args);
//Do something with the args...
}
void OtherMethod()
{
//I want to pass it back to the same method with the same arguments.
SaveTheseArgs(savedArgs);
}
}
//I tried a struct template like this, but this actually doesn't store them unless I am doing something wrong.
template<typename... Args>
struct StoredArguments
{
std::tuple<Args...> StoredArgs;
};
I am fairly new to C++ programming. I have some experience in other languages such as C#, AS3, Java.
Assuming I read your mind right, you save the args by not saving the args.
First, write this:
void DoOperation( std::tuple<int, double, std::string> const& tup ) {
auto&& some_arg_name = std::get<0>(tup);
auto&& second_arg_name = std::get<1>(tup);
// etc
// do stuff with the args
}
typedef std::function<void(TempClass*)> saved_operation;
saved_operation BuildOperation( int a, double b, std::string s ) const {
auto tup = std::make_tuple(a,b,s);
return [tup](TempClass* self){
return self->DoOperation(tup);
};
}
DoOperation takes a tuple, and does the operation using those arguments.
BuildOperation takes arguments, bundles them into a tuple, and generates a saved_operation from them.
saved_operation is basically a saved method call. I don't store this because by avoiding that, the default copy ctor does the right thing. Instead, you pass this in each time you use it.
Now using the above, we implement your stuff:
saved_operation saved_op;
template<typename ...Args>
void SaveTheseArgs(args&& ...args)
{
saved_op = BuildOperation(std::forward<Args>(args)...);
saved_op(this);
}
void OtherMethod()
{
assert(saved_op);
saved_op(this);
}
A copy of the tuple is actually stored inside the saved_operation object, but that is an implementation detail.
The trick is we care not about the data, but rather what we will do with the data later.
I used some concrete types (the int double etc), but those can just as easily be template methods as well.
If you need the efficiency, a bit more care involving moving data around instead of copying can be useful. But I kept it relatively simple. If you really need a pack of any args, you might have to google the "indexes trick" to unpack the tuple of unknown content back into parameters.
In this case, std::function is a type erasure class that erases the details of what it is constructed from, except for the fact it can be copied, destroyed, invoked with a particular signature (and also cast-back-to-source-type, which few people use).
We exploit this to "forget" the tuple and instead just remember the operation we want to do on the tuple.
This technique can be used in more general situations: you can type erase anything with a fixed signature, or really anything that can be boiled down to a fixed signature (which is a bit broader).
Words to search for for more on this topic include "runtime concepts" and "type erasure". Examining how std::function can be implemented.

Store pointers to memberfunctions of different classes

I am trying to store pointers to memberfunctions of different Classes in C++. What are the possibilities in C++?
I would like to do this:
class A {
T0 f(T1,T2);
};
class B {
T0 g(T1,T2);
T0 h(T1,T2); //interfaces cant be used since the number of functions per class differs.
};
typedef WHATTOPUTHERE type;
type x;
x = A::f;
x = B::h;
Update: Another Problem is that the code should be continueable like this:
B myB;
myB::x(a,b); //not sure about the syntax, should result in myB::h(a,b) being called
This means that I can not bind at the time I store the pointer, since the instance does not exist (yet).
Function objects to encapsulate your function pointers should work.
boost::function is one option, maybe something like this:
class SomeObj
{
public:
void SetInt(int i);
};
SomeObj myObject;
std::vector<boost::function> memberFuncs;
// in the template arg to boost::bind specify the function type
// _1 here denotes late binding so you can pass whatever value you want when invoked
// you could simply bind a parameter as a variable or literal instead
memberFuncs.push_back(boost::bind<void(int)>(&SomeObj::SetInt, &myObject, _1));
memberFuncs[0](42); // myObject->SetInt(42);
Untested/uncompiled code disclaimer this is just for a general idea.
One possible implementation (using C++11) can easily be done using std::function and a lambda like this:
typedef std::function<void(int)> FunctionType;
SomeClass someClass;
FunctionType func = [&someClass](int argument)
{
someClass.SomeMemberFunction(argument);
};
To have a pointer to Fred::f(char, float) you need this sort of pointer:
int (Fred::*)(char,float)
http://www.parashift.com/c++-faq-lite/pointers-to-members.html
The answer to your particular question is that there is no type that you can add to the typedef and make the code compile. The reason is that member function pointers take a hidden argument of the type of the class form which they are obtained. The type of that hidden argument will be different when you take the address of a member function from A or B.
The next question is whether it makes sense or not from a design perspective, considering that you cannot apply the function pointer A::f to an instance of type B, what is the point of considering member pointers of A and B together?
Now, there are possible workarounds for this particular problem (if it makes sense in your case, but I would first review the design) that involve performing type-erasure on the function pointer to remove the hidden argument and generate an object that is callable with the given set of arguments and return type that is common to all of the member functions. This is already done inside std::function (alternatively boost::function if your compiler does not support C++11), as has been suggested before:
A a_instance;
std::function< T0 (T1,T2) > f( std::bind( &A::f, &a_instance, _1, _2 ) );
T0 r = f( T1(), T2() );
Note that part of the trick is that std::bind binds the member function pointer with the pointer to the instance, filling in the hidden argument, while leaving the other two arguments unbound. At this point, because the result of bind does no longer depend on the type of the first argument, type-erasure can be applied removing A from the type of the resulting object.

Easy way of calling function with unknown args count via pointer

I have the following code:
typedef void * (__stdcall * call_generic)(...);
typedef void * (__stdcall * call_push2)(unsigned long,unsigned long);
void * pfunc;
// assume pfunc is a valid pointer to external function
// this is a logically correct way of calling, however this includes:
// add esp, 8
// after the call, and that breaks my stack.
((call_generic)pfunc)(1,1);
// however, if i use this call:
((call_push2)pfunc)(1,1);
// this does not happen and code works properly.
It's a pain to track all the calls and count args manually (there are lots of such calls ahead), I'd prefer a macro or something for this, but with that bug it's not possible.
Is there a solution? Is there another way of creating call_generic type to do such things?
I do not really understand why exactly it does that "cleanup" but that breaks my stack badly, causing previously defined variables to be lost.
((call_generic)pfunc)(1,1); is only a logically correct way of calling if the function pointed to by pfunc actually has the signature you cast to, void *(...). Your code tells the compiler to make a varargs call, so it makes a varargs call. A varargs call to a function that isn't a varargs function doesn't work (in this case, there's disagreement who has to clean up the stack, and it gets done twice).
There's no way to do this for free. You must somehow cast the function pointer to the correct signature before calling it, otherwise the calling code doesn't know how to pass the parameters in a way that the callee code can use.
One option is to ensure that all the called functions that pfunc might point to have the same signature, then cast to that type. For example, you could make them all varargs functions, although I don't particularly recommend it. It would be more type safe to do what you don't want to - make sure that all the functions that might appear here take two unsigned long, and cast to call_push2.
The trick with call_generic won't work with functions that should be called with __stdcall calling convention. This is because __stdcall implies that the function should clean the stack, OTOH variadic functions (those with ... arguments) may not do this, since they are not aware of the arguments.
So that marking a variadic function with __stdcall calling convention is like shooting yourself in the foot.
In your specific case I'd go in the macro writing direction. I don't see a trivial trick that'd acomplish what you need.
EDIT
One of the techniques may be using template classes. For instance:
// any __stdcall function returning void taking 2 arguments
template <typename T1, typename T2>
struct FuncCaller_2
{
typedef void * (__stdcall * FN)(T1, T2);
static void Call(PVOID pfn, T1 t1, T2 t2)
{
((FN) pfn)(t1, t2);
}
};
// call your function
FuncCaller_2<int, long>::Call(pfn, 12, 19);
You'll need to create such a class for every number of arguments (0, 1, 2, 3, ...).
Needless to say this method is "unsafe" - i.e. there is no compile-time validation of the correctness of the function call.
seems to me you want a form of dynamic function binding mechanism that will bind a pointer to a protoype deducted from an invocation. This generally requires metaprogramming, for this boost::bind or something else from the boost functions library is your best bet (and if they don't have it, its doubtful that i can be done).