动态C++函数参数
问题描述:
这很可能是错误的标题,但我不知道如何描述它。我想要做的是从我的脚本语言(运行在虚拟机中)调用C++函数。我遇到了一些麻烦,想知道如何将参数传递给函数。动态C++函数参数
我最好的解决办法,到目前为止是这样做:
void func(int a) {
// Start param copy
char c;
char* par_start = &c - sizeof(char) - getCurrentFuncParamOffset();
copyCurrentParams(par_start);
// End copy
// Code
}
然后,调用函数我第一次把它暴露在VM,将参数给它。这是一些缩短的代码,但所有内容都被转换为void(*),以便将其存储在散列表中。
EXPOSE(test, int);
vm.call("test", 12)
EXPOSE抓取指向函数测试的指针,并存储它需要单个进入的地方。它将指针作为void(*)()存储在散列表中,以便当我想调用它时,我可以从VM拨打电话并解析它。然后,函数内部的代码(我从问题中的宏中扩展而来)会将从调用传递给虚拟机的参数复制到函数的参数中。
这可行,但它不是最优雅的解决方案,尤其是因为我将不得不为每个我想为脚本公开的函数调用宏。有更好的解决方案吗?谢谢。
答
你可以使用C++所提供的。这是我扔在一起的一个小例子。现在
class ScriptObj {}; // Your type that encapsulates script objects.
// May be as simple as an integer or a string,
// or arbitrarily complex like PyObj
template <typename T> T from_script(ScriptObj); // conversion to and from
template <typename T> ScriptObj to_script(T); // C++ types. You provide
// specialized implementations.
// Bad conversions should throw.
// Abstract base class for C++ functions callable from the scripts.
// The scripting engine should pass a vector of parameters and a pointer to result.
struct script2cxx
{
virtual ~script2cxx() {}
virtual ScriptObj operator()(const std::vector<ScriptObj>& params) = 0;
};
// Concrete class that exposes a C++ function to the script engine.
template <class Res, class ... Param>
struct script2cxx_impl : script2cxx
{
using funcType = Res(*)(Param...);
virtual ScriptObj operator()(const std::vector<ScriptObj>& params)
{
if (sizeof...(Param) != params.size())
throw std::domain_error("Invalid size of parameter array");
return to_script<Res>(call_impl<std::tuple<Param...>>(func, params, std::make_index_sequence<sizeof...(Param)>()));
}
template <class Tuple, std::size_t... N>
Res call_impl(funcType func, const std::vector<ScriptObj>& params, std::index_sequence<N...>)
{
return func(from_script<typename std::tuple_element<N, Tuple>::type>(params[N])...);
};
funcType func;
script2cxx_impl(funcType func) : func(func) {}
};
// a helper biold function
template <class Res, class ... Param>
auto expose(Res(*func)(Param...)) {
return new script2cxx_impl<Res, Param...>(func);
}
,你可以在地图上标注的script2cxx
(智能)指针,并与你的脚本对象的载体给他们打电话。
std::map<std::string, std::unique_ptr<script2cxx>> exposed;
int foo(double, char[], int**) {...}
// below is the only line you need to add
// if you want to expose any standalone C++ function.
// no boilerplate.
exposed["foo"]=expose(foo); // you can wrap this in a macro if you want
,并呼吁他们:
std::vector<ScriptObj> somevector = ...;
std::string somestring = ...;
(*exposed[somestring])(somevector);
没有不安全的铸件和/或空指针在做这个例子中受到伤害。
+0
我以前从来没有使用模板的省略号,很好的解决方案!谢谢 – BlueSpud
您在“然后我做”下的部分与上述部分没有任何关联。真的很难理解足够的帮助。 – AndyG
@AndyG我很抱歉,希望编辑清除它 – BlueSpud
不完全。什么是EXPOSE宏?什么是“cppFunction”? void(* ptr)()=(void(*)());'? – AndyG