问个比较复杂的 C++的问题,有关模板的

2015-07-29 12:07:07 +08:00
 amaranthf
现在有这样一个需求,我需要一种和脚本交互的接口函数,以前是手写的:
void MyInterface(Info info)
{
auto iso = info.getIsolate();
int a = iso.getArgsInt(1);
float b = iso.getArgsFloat(2);
string c = iso.getArgsString(3);

auto r = RealFunc(a,b,c);

iso.setReturnValue(r);
}
这个函数会被注册到脚本引擎中,通过上述abc三行的方法获取脚本中传入的参数,然后调用C++函数RealFunc来进行处理,最后设置返回值。

现在希望通过模板来做到这一点,最好能做到这样:

只要调用
InterfaceGenerator<int, float, string>(RealFunc)
便可以返回给我一个函数,函数的内容就是上面写的MyInterface那样。具体模板参数和实际参数可以变化,但是需要返回给我那个函数。
可以使用C++11/14等标准……
3358 次点击
所在节点    程序员
13 条回复
soli
2015-07-29 12:48:43 +08:00
随便一写,你随便一看。

对不对的不知道哈。

```cpp

template<class R, class F, class S, class T>
void InterfaceGenerator( R (*RealFunc)(F, S, T) ) {
F f;
S s;
T t;
R r;

auto iso = info.getIsolate();
iso.getArgs(1, f);
iso.getArgs(2, s);
iso.getArgs(3, t);

r = RealFunc(f, s, t);

iso.setReturnValue(r);
}

class ISO {

void getArgs(int idx, int &i);
void getArgs(int idx, float &f);
void getArgs(int idx, string &s);

//...
};

bool RealFunc(int i, float f, string &s) {
//...
return true;
}

InterfaceGenerator<bool, int, float, string>(RealFunc);

```
soli
2015-07-29 12:49:30 +08:00
呃,看了评论仍然没有支持 Markdown 。。。

@Livid 老大,啥时候评论支持 Markdown 哈?
hitmanx
2015-07-29 16:23:08 +08:00
@soli 貌似InterfaceGenerator漏了输入参数Info。如果把这个参数加上的话,貌似Info和ISO也得弄成模板类才行。
soli
2015-07-29 16:27:51 +08:00
@hitmanx 对对,漏了 info 。

```cpp

template<class R, class F, class S, class T>
void InterfaceGenerator(Info info, R (*RealFunc)(F, S, T) ) {

```

这样应该差不多了。

Info 和 ISO 不需要弄成模板类吧。
hitmanx
2015-07-29 17:13:49 +08:00
@soli 实际应该有不止一种ISO类(如果只有一个ISO类,那么折腾这么多就没意思啦),也会有多种它的holder Info类。而void InterfaceGenerator(Info info, R (*RealFunc)(F, S, T) )中的第一个参数在这里已经限定了是唯一指定的类型,不用模板的话,可能需要把Info弄成基类,把Info::getIsolate()弄成接口函数才行。

不过话说我感觉这种情况如果只是这样的话,是不是用个简单的宏就行了,类似
#define InterfaceGenerator(info, func) \
do { \
auto iso = info.getIsolate(); \
iso.ret_ = func(iso.arg1_, iso.arg2_, iso.arg3_); \
} while(0)
knightzorro
2015-07-29 17:42:50 +08:00
参考tuple的实现吧。
amaranthf
2015-07-29 18:59:08 +08:00
@soli @hitmanx 非常感谢两位的回复。
但是很抱歉,是我的问题没说清楚……下午上班前看了下还没人回复,然后到现在才看到……

首先我所使用的这个引擎,在注册接口的时候,只接受指定形式的接口:

void CallbackFunc(const v8::FunctionCallbackInfo<v8::Value>& info);

所以我需要InterfaceGenerator返回这样一个函数,形如:

template <typename FuncType, typename Head, typename... Tail>
auto InterfaceGenerator(FuncType func)
{
return [func](const v8::FunctionCallbackInfo<v8::Value>& info) // lambda表达式
{
// 要返回的真正的函数体
};
}
然后我就可以这样进行注册:
bool myFunc(int, char*);
global->Set(“myFunc”, FunctionTemplate::New(isolate, InterfaceGenerator<int, char*>(myFunc)));
这里InterfaceGenerator的功能是利用模板参数和目标函数,返回一个新的函数,其实叫wrapper更合适……

其次转换每种参数的步骤是不一样的,不是单纯调用一个getArgs(int idx, float& f)就可以完成的,当然这一步我自己差不多知道怎么搞,写一个专用的使用模板的转换函数即可。

最后也是我最想实现的一点,就是变参模板……就像上面代码里面那样:
<typename Head, typename... Tail>
但是这一步也是问题最大的,用递归的话我实在想不出来怎么把参数依次传递到最终调用的地方。其他方式好像也拆不开参数列表……
xylophone21
2015-07-29 21:15:30 +08:00
你需要一个代码生成器。如果参数只是简单类型(不包括指针,回调,类等)的话,用python撸一个不难。
xylophone21
2015-07-29 21:24:00 +08:00
顺便做个广告,给你一个参考。简单撸的为Android Binder生成C++胶水代码的Python脚本。

https://github.com/xylophone21/android-binder-standalone

在sidl目录,脚本写的比较乱,轻喷。
amaranthf
2015-07-29 22:57:09 +08:00
@xylophone21 谢谢~代码生成器我以前也写过,用来生成一些重复性代码或者数据之类的东西。但是我觉得我的这个需求应该是可以通过模板来完成的……就是设计不出来……
yangff
2015-07-30 05:09:32 +08:00
yangff
2015-07-30 05:11:03 +08:00
顺便,模板还可以再优化一些,可以用模式匹配直接从func的类型中搞出agument list之类的。。
amaranthf
2015-07-30 13:02:21 +08:00
@yangff 谢谢,我学习一下……

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/209175

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX