我想与我从 C++ 程序编写的 C 库进行交互。 C 库是使用现代 C 编写的,并使用了 static
数组说明符以显示数组的最小长度,或者指针不能是 NULL
.
当我尝试编写一个与 extern "C"
接口(interface)的程序时使用此功能的功能我收到以下消息:
error: static array size is a C99 feature, not permitted in C++
不能与这个 C 库交互吗?我是否必须修改 C 库,或者是否有替代方案?
这是导致错误的示例程序:
// foo.h
#ifndef FOO_H
#define FOO_H
void foo(int i[static 1]);
#endif //FOO_H
// foo.c
#include <stdio.h>
void foo(int i[static 1]) {
printf("%i", i[0]);
}
// main.cpp
extern "C"
{
void foo(int i[static 1]);
}
int main() {
int i[] = {1};
foo(i);
}
最佳答案
extern "C"
向 C++ 编译器指示函数名称不应被破坏。由于您正在链接外部库,因此期望外部库有一个名为 foo
的函数(并且只有一个函数)。 . static
C99 及以后的数组大小中的关键字告诉编译器“这个数组将至少是这个大小”,这可能允许编译器进行某些优化(我不知道这些可能是什么优化,但考虑到它可以可能循环展开到 N = 4
,您在其中声明了 void foo(int i[static 5]);
如果您传递的数组不是至少这个大小,您可能会遇到麻烦。
直接的解决方案就是我们需要告诉 C++ 编译器:
foo
int *
作为参数extern "C"
{
void foo(int i[]);
}
但是我们丢失了在 C++ 程序中使用 this 的任何人的信息,即这个函数的大小必须至少为 N(这就是数组大小中的
static
关键字的含义)。我想不出一个好方法来强制对此进行编译时检查,除非可能通过某种类型的模板化包装函数:#include <cstddef>
extern "C"
{
void foo(int i[]);
}
template <std::size_t N>
void c_foo(int i[N])
{
static_assert(N >= 5);
foo(i);
}
int main(int argc, char** argv)
{
int a[5] = {1, 2, 3, 4, 5};
int b[4] = {1, 2, 3, 4};
c_foo<5>(a); // this will be fine
c_foo<4>(b); // this will raise a compile-time error
}
为了更加安全,我会为您的
c_foo
放置函数原型(prototype)。功能和任何“安全”extern "C"
原型(prototype)合二为一c_library_interface.h
文件,以及 c_foo
的函数定义函数和任何“不安全”extern "C"
另一个 c_library_interface_unsafe.cpp
中的原型(prototype)文件。那样的话,只要你不在你的主 C++ 文件中包含 unsafe 文件,你应该只能与 static
交互。数组大小函数通过模板,这将做一些大小检查。
关于c++ - extern "C"静态数组函数参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60517139/