C++ 将Gravity(脚本语言)调用转换为本机C函数调用
我目前正在研究实现一种更干净的方法,从脚本语言调用本机C函数 到目前为止,最简单的例子是:C++ 将Gravity(脚本语言)调用转换为本机C函数调用,c++,c,calling-convention,scripting-language,gravity-language,C++,C,Calling Convention,Scripting Language,Gravity Language,我目前正在研究实现一种更干净的方法,从脚本语言调用本机C函数 到目前为止,最简单的例子是: int add(int lhs, int rhs) { return lhs + rhs; } static void gravity_wrap_add( gravity_vm* vm, gravity_value_t* args, uint32_t nargs, uint32_t retIndex, void* data ) { int lhs, rhs, rt; // U
int add(int lhs, int rhs) {
return lhs + rhs;
}
static void gravity_wrap_add(
gravity_vm* vm,
gravity_value_t* args, uint32_t nargs,
uint32_t retIndex, void* data
) {
int lhs, rhs, rt;
// Unwrap
lhs = VALUE_AS_INT(args[1]);
rhs = VALUE_AS_INT(args[2]);
// Perform call, capture return
rt = add(lhs, rhs);
// Forward the return
gravity_vm_setslot(vm, VALUE_FROM_INT(rt), retIndex);
}
static void gravity_wrap_add(
gravity_vm* vm,
gravity_value_t* args, uint32_t nargs,
uint32_t retIndex, void* data
) {
gravity_vm_setslot(vm,
VALUE_FROM_INT(
add(VALUE_AS_INT(args[1]), VALUE_AS_INT(args[2]))
),
retIndex);
}
使用C++(98)模板或C预处理器魔术,有没有一种方法生成包装函数?< /P> 上述包装器函数的一个非常非常复杂的例子是:
int add(int lhs, int rhs) {
return lhs + rhs;
}
static void gravity_wrap_add(
gravity_vm* vm,
gravity_value_t* args, uint32_t nargs,
uint32_t retIndex, void* data
) {
int lhs, rhs, rt;
// Unwrap
lhs = VALUE_AS_INT(args[1]);
rhs = VALUE_AS_INT(args[2]);
// Perform call, capture return
rt = add(lhs, rhs);
// Forward the return
gravity_vm_setslot(vm, VALUE_FROM_INT(rt), retIndex);
}
static void gravity_wrap_add(
gravity_vm* vm,
gravity_value_t* args, uint32_t nargs,
uint32_t retIndex, void* data
) {
gravity_vm_setslot(vm,
VALUE_FROM_INT(
add(VALUE_AS_INT(args[1]), VALUE_AS_INT(args[2]))
),
retIndex);
}
<>这个版本在技术上是我想要达到的,但是通过像预处理器或C++模板这样的方法。出于跨平台兼容性的原因,我希望坚持使用C++98(因为MSVC在现代功能上并不太好)。没有可变模板的话,这是相当乏味的,但您应该能够执行一些参数:
namespace gravity {
template<class T> struct value {};
// for brevity and deduction:
template<class T> T get(const gravity_value_t &v)
{return value<T>::get(v);}
template<class T> gravity_value_t put(const T &t)
{return value<T>::put(t);}
template<> struct value<int> {
int get(const gravity_value_t &v)
{return VALUE_AS_INT(v);}
gravity_value_t put(int i)
{return VALUE_FROM_INT(i);}
};
// more specializations…
template<class R,R f()>
void wrap(gravity_vm* vm,
gravity_value_t* args, uint32_t nargs,
uint32_t retIndex, void* data) {
assert(nargs==0);
gravity_vm_setslot(vm,put(f()),retIndex);
}
template<class R,class A,R f(A)>
void wrap(gravity_vm* vm,
gravity_value_t* args, uint32_t nargs,
uint32_t retIndex, void* data) {
assert(nargs==1);
gravity_vm_setslot(vm,put(f(get<A>(args[0]))),retIndex);
}
// more overloads with more arguments…
/*gravity_register*/(wrap<int,int,int,add>);
}
名称空间重力{
模板结构值{};
//为了简洁明了:
模板T获取(常量重力值T&v)
{返回值::get(v);}
模板重力值输入(常数t&t)
{返回值::put(t);}
模板结构值{
int get(恒定重力值t&v)
{返回值_为_INT(v);}
重力值输入(int i)
{返回值_FROM_INT(i);}
};
//更多专业…
模板
无效包裹(重力_vm*vm,
重力值,
uint32_t重新索引,无效*数据){
断言(nargs==0);
重力(vm)(vm,put(f),retIndex);;
}
模板
无效包裹(重力_vm*vm,
重力值,
uint32_t重新索引,无效*数据){
断言(nargs==1);
重力(vm)设定点(vm,put(f(get(args[0])),retIndex ;;
}
//具有更多参数的更多重载…
/*重力寄存器*/(包裹);
}
像往常一样,void
返回类型将是一种痛苦;必须为void
的R
重复每个参数计数重载
在使用
wrap
时,可以使用演绎法来避免重复签名,但这样可以得到较少的函数和额外的闭包对象来区分它们(您可以通过data
参数来使用这些对象)。很难准确地说出您在尝试什么,但如果我理解,您可以包括limits.h
和gravity\u wrap\u add
validateINT\u MIN