场景是这样的。我看到一个结构在按值传递到回调函数时被损坏,从 C API 到 C++ 一个(通过静态方法)。
库 A:基于 C 的 API,通过 gcc 构建 库 B:基于 C++ 的 API,通过 g++ 构建
库 A 构建为带有 -fPIC 的静态库。库 B 构建为共享库,链接库 A,也使用 -fPIC 构建。
在库 A 中定义的是一个结构:
typedef struct doomed_struct
{
uint32_t field1;
uint32_t field2;
CHILD_STRUCT1 field3;
CHILD_STRUCT2 field3;
} DOOMED_STRUCT;
和一个回调函数:
typedef void (_CALLBACK_FUNC *FUNCTION)(uint32_t arg1, uint8_t arg2,
uint8_t arg3, DOOMED_STRUCT arg4);
C++ API 在类中定义了一个静态方法,并将其交给 C API 进行回调。当这个回调被调用时,简单的类型化 arg1,2,3 可以很好地完成它,但是结构中的字段是垃圾,并且每次执行都会改变。
我也尝试将 C++ API 的函数更改为extern "C"
静态函数,但没有运气。
如果我在 C API 中存根一个 C 函数并调用它只是为了测试,那么该结构将被很好地复制而不会损坏。
令人沮丧的部分?这一切都适用于 Linux 和 QNX 上的 MSVC8/9/10、gcc 4.4.x(32 和 64 位)。几年后回到 gcc 4.1,这会弹出。
如果我更改回调函数以通过指针而不是副本传递结构,它工作正常!唉,C API 有 ABI 限制,不能修改。
它闻起来像是某种调用约定或结构布局问题,但我不知道要为这样的事情转动什么旋钮。总体而言,该结构为 16 个字节,因此它不会对我产生堆栈问题。