gpt4 book ai didi

c++ - 使用 var_arg 为函数调用传递参数

转载 作者:太空宇宙 更新时间:2023-11-04 03:54:09 26 4
gpt4 key购买 nike

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

显然,它们不能直接映射,因为一个接口(interface)需要 C++ 编译,名称修改会破坏另一个接口(interface),所以这就是我首先使用一组适配器的原因。

随着参数数量的变化,我查阅了可变参数函数并发现这个想法非常有用,但是我只在 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/240000586but由于模板的使用,我不确定它是否会产生另一个问题,因此最终为每个函数调用实现一个适配器可能更简单。

SO 搜索只返回了这个:Dynamic function calls at runtime (va_list)

最佳答案

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

有时,仍然需要为 C++ 接口(interface)编写适配器,因为它操作不映射到 C POD 的对象。因此,适配器为 C 接口(interface)提供了一个 POD 或不透明指针类型来进行操作,但该接口(interface)的实现将其转换为 C++ 对象或引用,然后调用 C++ 接口(interface)。例如,假设您想为 C++ std::map<int, void *> 提供 C 接口(interface),您将在 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++ 代码可以实现如下功能:

typedef std::map<int, void *> 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<map_int_ptr *>(cmap);
map_int_ptr::iterator i = map.find(key);
if (i != map.end()) {
*data = i->second;
return 0;
}
return -1;
}

因此,无需通过可变参数适配器传递通过 C 接口(interface)传递的参数。因此,C++ 代码无需从可变参数列表中梳理出参数。 C 代码直接调用 C++ 代码,后者知道如何处理参数。

我想如果您正在尝试通过解析 C++ 代码来实现某种自动 C 适配器代码生成器,您可能会认为使用可变参数会提供一种常规机制来在生成的 C 代码接口(interface)和生成的 C++ 适配器之间传递参数调用原始 C++ 接口(interface)的代码。对于这种情况,上述示例的代码将如下所示:

// 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基于表查找的实例。

关于c++ - 使用 var_arg 为函数调用传递参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18404229/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com