将多维数组传递给外部"C"函数为 void *
Pass multidimensional array to extern "C" function as void *
我的库中有一个 C 函数,可以很好地处理多维数组:
void alx_local_maxima_u8 (ptrdiff_t rows, ptrdiff_t cols,
const uint8_t arr_in[static restrict rows][static cols],
bool arr_out[static restrict rows][static cols])
__attribute__((nonnull));
我有一个从 openCV 中定义的class
收到的unsigned char *
。 该指针表示二维数据,但事实并非如此,我必须将其与指针算术(unsigned char *img_pix = img->data + i*img->step + j;
)一起使用,我不是特别喜欢。
我创建了一个图像大小相同的bool
数组(这是一个真实的数组,所以我可以使用数组符号)来存储函数的结果。
我可以编写一个几乎完全相同的alx_local_maxima_u8()
副本,只使用指针和指针算术,但如果可以的话,我希望能够重用它。
编写一个以这种方式使用void *
的原型只是为了愚弄C++是否安全?
extern "C"
{
[[gnu::nonnull]]
void alx_local_maxima_u8 (ptrdiff_t rows, ptrdiff_t cols,
const void *arr_in,
void *arr_out);
}
理论上void *
可以保存 C 将接收的任何指针,而 C 将无法访问不属于这些指针的任何数据,所以我看到的唯一问题是将unsigned char *
别名为uint8_t *[]
,并在预期uint8_t *[]
的地方传递void *
,这可能会导致所有类型的链接器错误。 另外,我不知道 Cbool
和 C++bool
是否会在内存中转换为相同的东西(我希望如此)。
也许我应该用 C 编写一个包装器来接收void *
并将它们传递给实际函数,这样我就不需要愚弄C++。
性能是一个问题,但我使用-flto
,所以任何包装器都可能会在链接器中消失。
我在启用了POSIX的Linux中使用GCC(-std=gnu++17
)。
保证 T[N][M] 将包含 T 类型的 NxM 连续对象阻碍了一些其他有用的优化;在 C 的试行标准版本中,这种保证的主要用途是它允许代码在某些上下文中将存储视为一维数组,但在其他上下文中将存储视为多维数组。 不幸的是,标准没有认识到由内部数组衰减形成的指针与直接或通过void*
将外部数组转换为内部元素类型形成的指针之间的任何区别,即使它们对前者施加了限制,这会阻碍后者的有用性。
在任何典型的平台上,在没有全程序优化的情况下,ABI 会将指向多维数组元素的指针视为等效于指向具有相同元素总数的一维数组元素的指针,从而可以安全地将后者视为前者。 但是,我不相信 C 或 C++ 标准中有任何内容会禁止实现"优化"以下内容:
// In first compilation unit
void inc_element(void*p, int r, int c, int stride)
{
int *ip = (int*)p;
ip[r*stride+c]++;
}
// In second compilation unit
int array[5][5];
void inc_element(void*p, int r, int c, int stride);
int test(int i)
{
if (array[1][0])
inc_element(array, i, 0, 5);
return array[1][0];
}
通过将inc_element
调用替换为array[0][i*5]++
,这反过来又可以优化为array[0][0]++
。 我不认为标准的作者打算邀请编译器进行这样的"优化",但我不认为激进的优化者会将未能禁止此类事情解释为邀请。
将数组指针作为const void *
传递应该不会导致任何问题,但请注意,bool
在 C 和 C++ 中可能具有不同的表示形式。对数组基类型使用更显式的类型(如unsigned char
)会更安全。
为指针指定此类型也有助于提高可读性,因为可以使用p[r * cols + c]
直接对矩阵单元格进行寻址。
- 为什么随机数生成器不在void函数中随机化数字,而在main函数中随机化
- 在c++类上调用void函数
- 在派生函数中指定void*参数
- C++为什么尽管我调用了void函数,它却不起作用
- 如何从void函数输出字符串
- 为什么这个函数将"const char*"转换为"void* const"而不是"const void*"
- 将尾部调用void(i32,..)位转换为llvm::函数以获取FnAttribute
- 库函数需要一个 std::function<void(void)>,如何传入类函数?
- 如何将指针从一个void函数传递到另一个C++
- 为什么全局函数 void showA(A&x) 能够访问 A 类的私有成员?
- 如何将函数<void()>写入管道/套接字对?
- 错误:无法在没有对象的情况下调用成员函数'void Fortest::run()'|
- 标准的大小::函数<void(int&)>类型
- 如何函数<void(字符串消息)>绑定到成员函数?
- 函数void()返回一个值,而不是char或string
- 函数void QQuickWindow::setDefaultAlphaBuffer(bool useAlpha)的用途
- 错误 LNK2019:函数 "void __cdecl Padding(int)" 中引用未解析的外部符号___iob_func
- 我可以有一个~析构函数(void)吗?
- 函数<void(T)> 带有默认参数的参数
- 错误:参数太少,无法函数"void alpha(std::string*,student)"