MSVC和mingw之间的界面二进制是否兼容?

我正在开发一个库,允许其用户(驻留在同一进程中的其他库)交换数据缓冲区和流。 该库必须可以从MSVC和mingw代码中使用(更多兼容性不会受到伤害,但并非绝对必要)。 为了实现这一点,核心功能应该由一个小的,兼容编译器的接口提供,稍后可以通过用客户端代码编译的便利层隐藏。

该库的一个具有挑战性的方面是它必须具有可扩展性,以便客户端可以提供自己的缓冲区和流实现,但核心库接口在发布后必须保持稳定。 如果你对进一步的背景感兴趣,你可以在论坛讨论中看到它。

我试图了解编译器之间的二进制兼容性问题,但由于我是这个主题的新手,我会对我的结果感兴趣。 我对这里的标准定义的行为不感兴趣(结构可能无法通过测试),只有在兼容mingw和MSVC以及其他编译器的情况下(如果方便的话)。

特别是,这些结构是否兼容? 它们一律由函数指针组成,所以我不认为填充会成为问题。 另外,这里是必需的stdcall约定,还是cdecl也能工作? 我可以不指定它,因为这两个编译器将默认为cdecl? 我是不是该? 这是我现在所拥有的:

#include <stdint.h>

typedef struct {
        uint32_t (__stdcall *read)(void*, uint8_t*, uint32_t);
        void (__stdcall *write)(void*, const uint8_t*, uint32_t);
        uint32_t (__stdcall *getBytesLeft)(void*);
        uint8_t (__stdcall *destroy)(void*);
} SharedStreamInterface;

typedef struct {
        uint32_t (__stdcall *read)(void*, uint8_t*, uint32_t);
        void (__stdcall *write)(void*, const uint8_t*, uint32_t);
        uint32_t (__stdcall *getBytesLeft)(void*);
        uint8_t (__stdcall *destroy)(void*);

        uint32_t (__stdcall *getreadpos)(void*);
        uint32_t (__stdcall *getwritepos)(void*);
        uint32_t (__stdcall *getlength)(void*);
        void (__stdcall *setreadpos)(void*, uint32_t);
        void (__stdcall *setwritepos)(void*, uint32_t);
        void (__stdcall *setlength)(void*, uint32_t);
} SharedBufferInterface;

extern "C" {
        // Functions applicable for both buffers and streams
        __stdcall uint32_t readData(uint32_t id, uint8_t* data, uint32_t size);
        __stdcall void writeData(uint32_t id, const uint8_t* data, uint32_t size);
        __stdcall uint32_t getBytesLeft(uint32_t id);
        __stdcall void destroyStreamOrBuffer(uint32_t id);
        __stdcall uint8_t streamOrBufferExists(uint32_t id);

        // Functions only applicable for buffers
        __stdcall uint32_t getReadPos(uint32_t id);
        __stdcall uint32_t getWritePos(uint32_t id);
        __stdcall uint32_t getLength(uint32_t id);
        __stdcall void setReadPos(uint32_t id, uint32_t pos);
        __stdcall void setWritePos(uint32_t id, uint32_t pos);
        __stdcall void setLength(uint32_t id, uint32_t length);
        __stdcall uint8_t bufferExists(uint32_t id);

        // Adding new buffers/Streams
        __stdcall uint32_t addStream(SharedStreamInterface *interface, void *stream);
        __stdcall uint32_t addBuffer(SharedBufferInterface *interface, void *buffer);
}

编辑:这个项目的意图暂时搁置了一段时间,如果再次搁置,可能需要重新思考。 尽管如此,我仍然留下了这个问题,因为我仍然对答案感兴趣。


是的,它们将是兼容的。 这是struct的美丽。 只要你不引入填充问题(在你正确指出的情况下,这确实不是这种情况),或者在C ++中添加功能给struct ,这将导致 - 编译器特定的-vtable布局,这将会始终兼容。

您还会注意到,从Windows头文件中,COM接口的C声明使用struct s的方式与您的方式非常相似。

注意: SharedStreamInterface::destroy成员提出了是否还有一个“创建”这样的流的问题。 您可能也想分享。 但你的里程可能会有所不同

至于调用约定的问题, __cdecl__stdcall都应该在二进制文件中工作,但是我总是更喜欢__stdcall的另一个原因:它与更多的“语言”(即工具)兼容,而不是__cdecl

对于样式:使用#define来明确地声明调用约定(与您一样),类似于Windows头文件中的WINAPI

链接地址: http://www.djcxy.com/p/7215.html

上一篇: Is this interface binary compatible between MSVC and mingw?

下一篇: How to let user know he/she needs to install another app that my app depends on