本文编写 visualfc
写一个invoke函数以支持任意参数调用,实现类似以下的功能代码。注:本代码纯属试验。
- class a
- {
- void func1(int,int);
- void func2(char*,int);
- };
- void invoke(a*,char * method,...);
- void test()
- {
- a a1,
- invoke(&a1,"func1",10,20);
- invoke(&a2,"func2","ok",0);
- }
我目前试验了三种方式,第一种是模板方式实现,第二种是基于可变参数(...)实现,第三种是使用类似boost::any的方式来实现。比较三种方式,
模板方式实现起来尤其不易,但是能够做参数检查,问题在于只能存在在头文件中。 第二种为可变参数方式,
本文给出了这种方式的试验代码,实现起来也比较简单,问题是无法验证参数。第三种方式为以类似any的方式来实现,但是实现效率则相对较低。
下面给出了第二种方式,即使用可变参数调用的实现,没有使用va_list和va_arg,这是因为函数调用栈顺序的原因,我使用了自定义的get_arg_back函数来获取可变参数。
- template <typename T>
- T get_arg_back(char ** parg)
- {
- *parg -= sizeof(T);
- T t = *((T*)*parg);
- return t;
- }
- template <typename R, typename CLS, typename T1, typename T2>
- R invoke_cls(CLS * pcls, R (CLS::*ptr)(T1,T2), char ** parg)
- {
- char * end = *parg+sizeof(T1)+sizeof(T2);
- return (pcls->*ptr)(get_arg_back<T1>(&end),get_arg_back<T2>(&end));
- }
- class a
- {
- public:
- int test(char * buf, int i)
- {
- printf ("test %s %d\n",buf,i);
- return 0;
- }
- int test2(int i, char * buf)
- {
- printf ("test2 %s %d\n",buf,i);
- return 100;
- }
- };
- void invoke(void * ptr, char * method,...)
- {
- char * parg = (char*)&method+sizeof(method);
- if (method == "test")
- invoke_cls((a*)ptr,&a::test,&parg);
- else if (method == "test2")
- invoke_cls((a*)ptr,&a::test2,&parg);
- parg = NULL;
- }
- int main(int argc, char* argv[])
- {
- a a1;
- invoke(&a1,"test","ok",1);
- invoke(&a1,"test2",1,"ok");
- return 0;
- }