如何从C++中最好地调用具有C99风格数组函数签名的函数

How to best call functions with C99-style array function signatures from C++

本文关键字:函数 风格 C99 数组 调用 C++      更新时间:2023-10-16

我正在用C++编写一些代码,需要调用用C99编写的库。此库使用C99样式的数组声明,函数参数中包含static关键字。即:

void my_func(int n, int my_ints[static n]);

然而,当在我的C++项目中包含这个库的头时,编译器(clang)在使用-pedantic标志时抛出警告:

> g++ -pedantic -c my_code.cpp
In file included from my_code.cpp:
./my_c_lib.h: warning: variable length arrays are a C99 feature [-Wvla-extension]
void my_func(int n, int my_ints[static n]);

在这种情况下,调用C库的正确/最佳方式是什么?除了关闭vla-extension警告之外,是否还有一些方法可以绕过它,不需要重写库的头或编写中间的C包装器?

最小工作示例:

extern "C" {
    void my_func(int n, int my_ints[static n]);
}
int main()
{
    int* some_ints = new int[10];
    my_func(10, some_ints);
    delete[] some_ints;
    return 0;
}

事实是,C++根本没有像C99那样强大的VLA,而且很可能永远不会有;将VLA纳入该语言的进展受到了严重限制,几乎毫无用处。

也就是说,您最好的选择可能是为您实际使用的库函数编写一些包装器,这些包装器公开风格的接口

void my_func_wrap(int n, int* my_ints);

这些将在C99文件中实现,如下所示:

void my_func_wrap(int n, int* my_ints) {
    my_func(n, my_ints);
}

C头和带有实现的文件都可以从库头自动生成,因为更改几乎是微不足道的。现在,您可以在没有任何类型冲突的情况下从C++代码中调用包装器。


第二种可能的方法是编写从库头中剥离所有[]括号内容的脚本,并使用它。这将完美地工作,因为即使在C99中,声明

void my_func_wrap(int n, int my_ints[static n]);

衰变为

void my_func_wrap(int n, int* my_ints);

这就是为什么我不需要在上面的包装器函数中进行任何强制转换的原因(我知道这听起来很疯狂,但这是事实)。只是您的C++编译器不喜欢第一个语法变体。

有没有一种方法不涉及重写库的头或编写中间C包装器?

当然,您可以将整个c头包含在extern语句中:

extern "C" {
    #include "my_c_lib.h"
}