Reputation: 7699
Consider the following situation:
You are given the pointer to a function as a raw pointer
void * function_pointer;
and the arguments to be passed to the function are available as a vector of a union type.
union Types {
void *ptr;
float *ptr_float;
double *ptr_double;
float fl;
int in;
double db;
bool bl;
};
std::vector<Types> arguments;
Thus, the functions' signature is only available in program state (as opposed to be known at compile time)
What would be the recommended way (C++ 11) to make this call ?
It would be possible to alter the arguments vector to something like this:
std::vector< std::pair<int,Types> > arguments;
where the first element of the pair would clearly identify of which type the argument is.
Technically, the signature is only given in the second form. Because only in the first form you can't tell what's the signature like.
Upvotes: 6
Views: 759
Reputation: 122439
In standard C, you must know the signature of a function (at compile time) in order to call it. Calling a function that is of one signature with a function pointer declared of the wrong signature will lead to undefined behavior.
There are libraries that use system-dependent assembly to construct function calls at runtime, like libffi.
Upvotes: 2
Reputation: 1294
There are existing libraries that can do what you describe, such as C/Invoke:
http://www.nongnu.org/cinvoke/
Upvotes: 1
Reputation: 23500
I cannot find a way to "bind" the pointer to an std::function
object.. perhaps you might figure that out or someone else.. but this is as good as it gets I guess.. It might be do-able in assembly/inline-assembly though.
#include <functional>
#include <iostream>
#include <vector>
void Meh(int X, int Y)
{
std::cout<<"Meh Arguments-> X: "<<X<<" Y: "<<Y<<"\n";
}
void Foo(std::string T)
{
std::cout<<"Foo Arguments-> "<<T<<"\n";
}
void FuncAddr(int Args)
{
std::cout<<"FuncAddr Arguments-> "<<Args<<"\n";
}
typedef void (*FuncPtr)(int);
int main()
{
void* Ptr = (void*)&FuncAddr;
std::vector<std::function<void()>> functions;
functions.push_back(std::bind(Meh, 1, 2));
functions.push_back(std::bind(Foo, "Hey"));
functions.push_back(std::bind((FuncPtr)Ptr, 200)); //Perhaps there is a way to "bind" the Pointer without the cast.. Not sure how though..
for (auto it = functions.begin(); it != functions.end(); ++it)
{
(*it)();
std::cout<<"\n";
}
}
Upvotes: 0
Reputation: 1795
Could you not just pass the union itself to the function and let it deal with what it wants? That way all the signatures are the same. If the argument isn't clear from context perhaps even pass two arguments, one saying what the union data is.
Finally if you MUST call a function which you cannot change the signature of I feel the only way is to use a switch
, casting the pointer to the right signature before calling.
Upvotes: 1