Re: Call unknown function by pointer
On 21 May, 21:47, kankan <yuri.kaniv...@gmail.com> wrote:
There are pointer to function and a list of arguments for it
(arguments types in known).
It needs to call this function with this arguments.
Here is a complete solution.
Instead of your struct Arg I'll use boost::variant.
Declarations:
#include <string>
#include <deque>
#include <boost/variant.hpp>
typedef boost::variant<int, std::string> Arg;
typedef std::deque<Arg> Args;
void Call(void* f, Args args);
Usage example:
void F1() {
std::cout << "F1()" << std::endl;
}
void F2(int a) {
std::cout << "F2(" << a << ")" << std::endl;
}
void F3(int a, std::string b) {
std::cout << "F3(" << a << ", " << b << ")" << std::endl;
}
int main() {
Arg args[] = { 42, "hello" };
Call(reinterpret_cast<void*>(F1), Args());
Call(reinterpret_cast<void*>(F2), Args(args, args + 1));
Call(reinterpret_cast<void*>(F3), Args(args, args + 2));
}
Implementation of function Call:
#include <cstdlib>
#include <string>
#include <deque>
#include <boost/variant.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/size.hpp>
#include <boost/fusion/mpl/at.hpp>
#include <boost/fusion/mpl/size.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/include/push_back.hpp>
#include <boost/fusion/include/make_fused.hpp>
#include <boost/fusion/include/as_vector.hpp>
// Current implementation support function with
// 0 - 2 arguments.
// If you need more, change this constant and add
// more specializations to make_function_impl.
static const size_t kMaxArguments = 2;
// List of supported argument types can be extended.
// Just add more stuff here.
typedef boost::variant<int, std::string> Arg;
typedef std::deque<Arg> Args;
template <class R, class A, size_t N>
struct make_function_impl;
template <class R, class A>
struct make_function_impl<R, A, 0> {
typedef R type();
};
template <class R, class A>
struct make_function_impl<R, A, 1> {
typedef R type(typename boost::mpl::at_c<A, 0>::type);
};
template <class R, class A>
struct make_function_impl<R, A, 2> {
typedef R type(typename boost::mpl::at_c<A, 0>::type,
typename boost::mpl::at_c<A, 1>::type);
};
// Given a return type and an mpl sequence of
// argument types, constructs a function type.
//
// Example:
// make_function<
// int,
// boost::mpl::vector<char, void*>
// >::type == int(char, void*)
template <class R, class A>
struct make_function :
make_function_impl<R, A, boost::mpl::size<A>::value> {};
template <class A>
void CallImpl(void* f, const A& first, Args& second);
template <size_t N, class A>
struct Caller : boost::static_visitor<void> {
Caller(void* f, const A& first, Args& second)
: f_(f), first_(first), second_(second) {}
template <class T>
void operator()(const T& arg) const {
CallImpl(f_,
boost::fusion::push_back(first_, arg),
second_);
}
private:
void* f_;
A first_;
Args& second_;
};
template <class A>
struct Caller<kMaxArguments, A>
: boost::static_visitor<void> {
Caller(void*, const A&, Args&) {}
template <class T>
void operator()(const T&) const {
std::cerr << "Too many arguments." << std::endl;
abort();
}
};
template <class A>
void CallImpl(void* f, const A& first, Args& second) {
if (second.empty()) {
typedef typename make_function<
void,
typename boost::fusion::result_of::as_vector<A>::type
>::type F;
boost::fusion::make_fused(reinterpret_cast<F*>(f))(first);
} else {
Arg front(second.front());
second.pop_front();
boost::apply_visitor(
Caller<boost::mpl::size<A>::value, A>(
f, first, second), front);
}
}
void Call(void* f, Args args) {
CallImpl(f, boost::fusion::vector<>(), args);
}
HTH,
Roman Perepelitsa.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]