使用var_arg传递函数调用的参数

我正在编写一个适配器来组合两个API(一个在C中,另一个在C ++中)。 如果在一个API上调用一个函数,我需要将调用者ID和函数的参数传递给适配器,并在传递此信息的情况下调用相应的函数。

现在显然它们无法直接映射,因为一个接口需要C ++编译,名称修改会使另一个接通,所以这就是我首先使用一组适配器的原因。

由于参数的数量不同,我查找了可变参数函数,并发现这个想法非常有用,但是我只在POD上运行,并且必须处理每个调用的结构,枚举和许多不同的参数,这可能需要放回去在将其提供给目标函数之前进入结构体。

我偶然发现的每个例子都比较简单,主要涉及算术操作,例如总结,查找最大数字或打印。 主要使用var_list上的for循环完成。

也许我陷入了这个想法,它根本不起作用,但我只是好奇……

假设我想将列表中的参数分配给我的目标函数参数(传递的参数的顺序是正确的),这会是一个好方法吗?

BOOL Some_Function( /* in */ CallerId *pObjectId, /* in */ someDataType argument1 ) { BOOL ret = Adapter_Call(pFunction, pObjectId, argument1); return ret; } 

所以一旦我把它做成了正确的适配器,我想做

 BOOL Adapter_Call(*pFunction, *pObjectId, argument1, ...) { va_list args; va_start(args, argument1); /*go over list and do `var_list[i] = pFunctionArgList[i]` which is of whatever type so I can use it as input for my function */ va_end(args); pObjectId.pFunction(arg1,...,argn); } 

我可以访问函数的输入参数来执行这样的赋值吗? 以前有人做过这样的事吗? 我的想法中存在概念上的错误吗?

我在网上找到的只有这个, http://www.drdobbs.com/cpp/extracting-function-parameter-and-return/240000586但是由于使用模板,我不确定它是否会产生另一个问题因此,最终为每个单独的function调用实现适配器可能更容易。

SO搜索仅返回此内容: 动态函数在运行时调用(va_list)

首先,你应该注意Kerrek关于extern "C"的建议。 这是C ++提供标识符C链接的机制,这意味着该名称不会被C ++编译器破坏。

有时,仍然需要为C ++接口编写适配器,因为它操纵不映射到C POD的对象。 因此,适配器为C接口提供了一个POD或opaque指针类型来进行操作,但该接口的实现将其转换为C ++对象或引用,然后调用C ++接口。 例如,假设您想为C ++ std::map提供C接口,您将在C和C ++中使用包含以下内容的公共头文件:

 #ifdef __cplusplus extern "C" { #endif struct c_map_int_ptr; // ... // return -1 on failure, otherwise 0, and *data is populated with result int c_map_int_ptr_find (struct c_map_int_ptr *, int key, void **data); #ifdef __cplusplus } #endif 

然后,C ++代码可以实现如下function:

 typedef std::map map_int_ptr; int c_map_int_ptr_find (struct c_map_int_ptr *cmap, int key, void **data) { map_int_ptr &map = *static_cast(cmap); map_int_ptr::iterator i = map.find(key); if (i != map.end()) { *data = i->second; return 0; } return -1; } 

因此,不需要通过可变参数适配器传递通过C接口传递的参数。 因此,C ++代码不需要从变量参数列表中梳理出参数。 C代码直接调用C ++代码,该代码知道如何处理参数。

我想如果你试图通过解析C ++代码来实现某种自动C适配器代码生成器,你可以认为使用变量参数将提供一个常规机制来在生成的C代码接口和生成的C ++适配器代码之间传递参数。调用原始的C ++接口。 对于这种情况,上面示例的代码看起来像这样:

 // C interface typedef struct c_map_int_ptr c_map_int_ptr; typedef struct c_map_int_ptr_iterator c_map_int_ptr_iterator; //... c_map_int_ptr_iterator c_map_int_ptr_find (c_map_int_ptr *map, int key) { c_map_int_ptr_iterator result; cpp_map_int_ptr_adapter(__func__, map, key, &result); return result; } // C++ code: struct cpp_adapter { virtual ~cpp_adapter () {} virtual void execute (va_list) {} }; void cpp_map_int_ptr_adapter(const char *func, ...) { va_list ap; va_start(ap, func); cpp_map_int_ptr_adapter_method_lookup(func).execute(ap); va_end(ap); } //... struct cpp_map_int_ptr_find_adapter : cpp_adapter { void execute (va_list ap) { map_int_ptr *map = va_arg(ap, map_int_ptr *); int key = va_arg(ap, int); c_map_int_ptr_iterator *c_iter = va_arg(ap, c_map_int_ptr_iterator *); map_int_ptr::iterator i = map->find(key); //...transfer result to c_iter } }; 

其中cpp_map_int_ptr_adapter_method_lookup()根据表查找返回适当的cpp_adapter实例。

Interesting Posts