c - 将一组动态的可变参数传递给 C 函数

标签 c variadic-functions

<分区>

我正在尝试调用一个采用可变参数的 C 函数,我需要将动态数量的参数传递给该函数。此外,这是一个我不付出很多努力就无法修改的 API,所以如果有任何可能使这项工作可行,我会接受它。

据我所知,va_list 不足以满足此目的,因为您不能传递 va_list where ...写在原始函数签名中。

其他问题的答案,例如 this one谈论如何将 ... 从一个函数传递到另一个函数,但这不是我正在做的。我需要实际动态生成参数列表,我没有将其作为 ... 获取。此外,我能找到的所有答案都依赖于能够修改函数以采用 va_list,这在此处不是一个选项。

还有 this question ,尽管实际上并没有问同样的问题,但它被标记为上一个问题的骗局。同样,唯一的答案是建议将调用转换为使用 va_list,这不是一个选项。

如果标准不包含执行此操作的方法,我会理解,但在这种情况下,我可以想象一个完全合理的实现。这与 alloca 没有太大区别。无论如何,如果不可能,那很好,但我希望 SO 社区意识到这不是 this question 的骗局。并且值得一个明确的答案。

我正在调用的 API 是用 C 编写的,但如果有一种方法可以用 C++ 执行此操作,我会考虑。

编辑:如果您有这些要求,它看起来像this answer using libffi是最好的方法。似乎没有办法在标准 C 或 GCC 扩展中执行此操作。

最佳答案

如果您使用 gcc 编译器,您可以使用 __builtin_va_arg_pack() 或 __builtin_apply(),参见 here .

例子:

#include <stdio.h>
#include <stddef.h>
#include <stdarg.h>

int my_printf(const char *fmt, ...)
{
    void *args = __builtin_apply_args();
    void *ret = __builtin_apply((void(*)())printf, args, 100);
    __builtin_return(ret);
}

extern int my2_printf(const char *, ...);
extern inline __attribute__((__always_inline__,__gnu_inline__))
int my2_printf(const char *fmt, ...) {
    return printf(fmt, __builtin_va_arg_pack());
}

int main()
{
    my_printf("%s %s %s %s %s\n", "Hi", "I", "am", "kamil", "!");
    my2_printf("%s %s %s %s\n", "Variadic", "args", "are", "fun");
    return 0;
}

@编辑:
由于问题还涉及如何构建动态参数列表,然后将其传递给函数。您可以为每个需要支持的案例创建一个函数,并使用一个大开关来区分它们。
打印未知编译大小数组的示例:

#include <stdio.h>
#include <stddef.h>
#include <stdarg.h>
#include <stdlib.h>
#include <boost/preprocessor/repetition/repeat.hpp>

void print_array(size_t cnt, ...)
{
        va_list va;
        va_start(va, cnt);
        printf("%s cnt=%d :", __func__, cnt);
        for (size_t i = 0; i < cnt; ++i) {
                printf(" %d", va_arg(va, int));
        }
        va_end(va);
        printf("%s\n");
}

// we support an array up to that many arguments
#define CALL_PRINT_ARRAY_MAX  128


#define CALL_PRINT_ARRAY_ARGS(z, n, text) \
        , arr[n]
#define CALL_PRINT_ARRAY_DECLARE(z, n, text) \
void call_print_array_##n (int arr[]) \
{ \
        print_array(n BOOST_PP_REPEAT(n, CALL_PRINT_ARRAY_ARGS, ())); \
}
BOOST_PP_REPEAT(CALL_PRINT_ARRAY_MAX, CALL_PRINT_ARRAY_DECLARE, ())
#undef CALL_PRINT_ARRAY_DECLARE
#undef CALL_PRINT_ARRAY_ARGS

int call_print_array(int arr[], size_t n)
{
        switch(n) {

#define CALL_PRINT_ARRAY_CASE(z, n, text) \
        case n: call_print_array_##n(arr); break;
                BOOST_PP_REPEAT(CALL_PRINT_ARRAY_MAX, CALL_PRINT_ARRAY_CASE, ())
#undef CALL_PRINT_ARRAY_CASE

        default:
                fprintf(stderr, "Array size is too big for what we're prepared\n");
                return -1;
        }
        return 0;
}

int main()
{
        //int a1[5] = {1,2,3,4,5};
        //call_print_array(a1, sizeof(a1)/sizeof(a1[0]));

        size_t size;
        scanf("%zu", &size); // insecure
        int * a2 = calloc(size, sizeof(*a2));
        for (size_t i = 0; i < size; ++i)
                a2[i] = i;
        call_print_array(a2, size);


        return 0;
}

关于c - 将一组动态的可变参数传递给 C 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50957748/

相关文章:

c - 使用 C API 迭代 GEOS Polygon 中的点

c++ - 使用 std::forward 进行参数包扩展的 '...' 的语法

c - stdarg 和 NULL 参数

c++ - 麻省理工学院球体模拟设置中的 Matlab 错误

c - C 代码中没有重复

c - 为什么代码在 Linux 上运行而不在 Windows 上运行?

带N个参数的C++方法

c - 可变参数函数 (va_arg) 不适用于 float ?

java - Java 可变参数的接收顺序是否与它们的接收顺序相同?

c++ - 移动设备的最佳加密库?