visual-c – MSVC和mingw之间的接口二进制兼容吗?

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

该库的一个具有挑战性的方面是它必须是可扩展的,以便客户端可以提供自己的缓冲区和流实现,但核心库接口必须在发布后保持稳定.如果您对更多背景感兴趣,可以在forum thread discussion中阅读.

我试图了解编译器之间二进制兼容性的问题,但由于我是这个主题的新手,我会对我的结果发表评论.我对这里的标准定义行为不感兴趣(结构可能无法通过该测试),只有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*,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);
}

编辑:这个项目的目的已暂停了一段时间,如果它再次没有得到解决,可能需要进行大量的重新思考.我离开了这个问题,因为我仍然对答案感兴趣.

解决方法

是的,它们是兼容的.那是结构的美.只要你没有引入填充问题(这在你正确指出的情况下确实不是这种情况),或者在C中添加结构的功能,这将导致 – 编译器特定的 – vtable布局,这将是始终兼容.

您还会注意到,从Windows头文件中,COM接口的C声明使用的结构与您的结构大致相同.

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

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

对于样式:使用#define显式声明调用约定(就像你一样)从Windows头文件中声明类似于WINAPI.

相关文章

本程序的编译和运行环境如下(如果有运行方面的问题欢迎在评...
水了一学期的院选修,万万没想到期末考试还有比较硬核的编程...
补充一下,先前文章末尾给出的下载链接的完整代码含有部分C&...
思路如标题所说采用模N取余法,难点是这个除法过程如何实现。...
本篇博客有更新!!!更新后效果图如下: 文章末尾的完整代码...
刚开始学习模块化程序设计时,估计大家都被形参和实参搞迷糊...