Я пытаюсь создать общий способ обернуть функции С++ (с другого языка). У меня есть список параметров (и итератор) и конкретная функция С++, которая вызывается в списке параметров. Я пытаюсь найти способ распаковать список параметров в качестве аргументов моей функции.
Мой текущий подход заключается в следующем:
- Используйте Boost::FunctionTypes, чтобы получить параметры функции в виде последовательности.
- Создайте список Boost::Fusion, который будет содержать значения аргументов, используя значения типов параметров для приведения.
- Вызовите функцию с созданным списком с помощью вызова boost::fusion.
Оба шага (1) и (2) кажутся довольно простыми. Однако я не могу понять, как сделать второй шаг (и если это вообще возможно - смешивание времени компиляции и времени выполнения кажется немного странным).
Кто-нибудь знает, как сделать второй шаг или как лучше подойти к этой проблеме?
Я знаю, что Boost::Python должен делать что-то подобное, но код немного запутан, чтобы получить хорошее представление о том, что происходит.
обновить
У меня есть частичное решение, которое работает (по крайней мере) для простых случаев. Есть еще проблемы с обращением со ссылкой.
Надеюсь, кто-то может опубликовать что-то лучшее решение.
Список содержит указатели на базовый класс A, от которого происходят все остальные используемые классы. У меня есть два подкласса B и C, которые содержат разные типы значений (int и string).
Оператор convert берет заданный класс и получает базовое значение. Эти значения собираются преобразованием в последовательность, которая затем передается для вызова.
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");
}
и, наконец, для вызова функции:
// 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);