В двух строках: создайте функцию интерфейса, которая принимает команду в виде строки и устанавливает функтор, который затем присваивается std::function
. operator()
позаботится об оценке строки на целевом языке.
Давайте предположим, что в файле заголовка mymodule.hh
у вас есть класс MyModule
с методом void MyModule::Func(const std::function<double(Bunch&)> & func)
где Bunch
является другой объект.
Это можно решить, определяя функцию интерфейса, которая принимает const char *
, представляющую выражение для eval, и переносит его в функтор, который затем будет присвоен std::function
. Хорошая новость заключается в том, что это может полностью сделано в файле интерфейса Swig, не касаясь кода C++, вот как (я использовал Tcl, вы просто должны адаптировать operator()
):
%module mymodule
%{
#include "bunch.hh"
#include "mymodule.hh"
extern Tcl_Interp* tcl_interp;
struct Tcl_bunch_callback {
std::string callback;
double operator()(Bunch & bunch)
{
Tcl_Obj * bunch_obj = SWIG_Tcl_NewInstanceObj(tcl_interp, &bunch, SWIGTYPE_p_Bunch, /*own pointer?*/0);
Tcl_SetVar2Ex(tcl_interp, "bunch", (const char*)nullptr, bunch_obj, 0);
double resultValue;
const int resultCode = Tcl_ExprDouble(tcl_interp, callback.c_str(), &resultValue);
if (resultCode != TCL_OK) {
std::cerr << "WARNING evaluation of tcl expression failed: "
<< Tcl_GetStringResult(tcl_interp) << std::endl;
resultValue = max_double;
}
Tcl_DeleteCommand(tcl_interp, Tcl_GetString(bunch_obj)); //remove the used command to avoid leaks
return resultValue;
}
};
%}
%include "bunch.hh"
%include "mymodule.hh"
%extend MyModule
{
void Func(const char * cmd) {
$self->Func(std::function<double(Bunch&)>(Tcl_bunch_callback(cmd)));
}
}
В моем случае operator()
довольно ограничена Tcl, но я уверен, что подобные процедуры могут быть написаны и для других целевых языков. Следуйте за некоторыми подробностями.
Я предоставляю пользователю возможность доступа к методам текущего Bunch
, обрабатываемых на C++ непосредственно из Tcl. Функция: SWIG_NewInstanceObj
позволяет преобразовать указатель Bunch
в его представление на целевом языке и создать экземпляр его в интерпретаторе (эта функция не документирована, но копает бит в любом сгенерированном swig файле обложек, это не так сложно понять его механизм). С помощью следующей команды я установил этот объект в переменную с именем bunch
, чтобы она стала доступной пользователю просто с $bunch
, и все методы, экспортированные с помощью swig, затем доступны.
Я думаю, это потрясающе, как такие мощные вещи доступны с такими небольшими строками кода благодаря swig!
Не уверен, что это вариант, но это было бы «относительно» легко сделать с помощью Boost Python. –
См. Мой ответ на http://stackoverflow.com/a/11522655/168175, который фактически использовал 'std :: function' в качестве примера. – Flexo