问题
I'm trying to create a generic way to wrap C++ functions (from a different language). I have a list of parameters (and and an iterator) and a specific C++ function to be called on the list of parameters. I'm trying to find someway to unpack the list of parameters as arguments to my function.
My current approach is to:
- Use Boost::FunctionTypes to get the parameters of the function as a sequence.
- Create a Boost::Fusion list that would contain the values of the arguments, using the values of the parameter types for casting.
- Call the function with the created list using boost::fusion's invoke.
Both the steps (1) and (2) seem fairly straightforward to do. However, I can't figure out how to do the second step (or if it's even possible -- mixing compile-time and run-time seems a little strange).
Does anyone have any idea of how to either do the second step, or a better approach on this problem?
I know Boost::Python has to do something similar, but the code is a little dense to get a good sense of what is happening.
update
I have a partial solution, which works for (at least) simple cases. There's still problems with dealing with reference.
Hopefully someone can post something better solution.
The list contains pointers to a base class A, from which all other classes used are derived. I have two subclasses B and C which contain different value types (int and string).
The operator convert takes the given class and gets the underlying value. These values are collected by transform into a sequence which is then given to invoke.
class A {
public:
A() {}
virtual ~A() {}
};
class B: public A {
protected:
int value;
public:
B() {}
B(int v): value(v) {}
int getValue() { return value; }
};
class C: public A {
protected:
string value;
public:
C() {}
C(const string &v): value(v) {}
string &getValue() { return value; }
};
// this pattern was copied from the test files from the fusion library
struct convert {
// keep a reference to the parameter we're going to unpack
list<A *>::iterator ¶m;
convert(list<A *>::iterator ¶m): param(param) {}
template<typename Sig>
struct result;
template <typename T>
struct result<convert(T)> {
typedef T type;
};
// this must be specialized in order to properly deal with the return types
template <typename T>
T operator ()(T type) const {}
};
template <>
int convert::operator ()(int type) const {
B *b = dynamic_cast<B *>(*param++);
if (b != NULL) return b->getValue();
throw error("illegal cast");
}
template <>
string convert::operator ()(string type) const {
C *c = dynamic_cast<C *>(*param++);
if (c != NULL) return c->getValue();
throw error("illegal cast");
}
and finally, to call a function:
// create a parameter list (usually this would be passed to us)
list<A *> params;
params.push_back(new B(2));
params.push_back(new C("test"));
// point to beginning of parameter
list<A *>::iterator pos = params.begin();
// foo is the function we're going to call,
typedef BOOST_TYPEOF(foo) params_type;
// use the parameter list of foo to unpack the parameter list
auto passedParams = fusion::as_list(fusion::transform(function_types::parameter_types<params_type>(), trans(pos)));
// finally, call foo with the sequence that was created by the transform
fusion::invoke(foo, passedParams);
来源:https://stackoverflow.com/questions/11164914/how-to-generate-wrappings-for-c-functions