Совместим ли этот двоичный интерфейс между MSVC и mingw?

Я работаю над библиотекой, которая позволяет ее пользователям (другим библиотекам, находящимся в том же процессе) обмениваться буферами данных и потоками. Библиотека должна использоваться как из кода MSVC, так и из кода mingw (большая совместимость не повредит, но не является строго необходимой). Чтобы достичь этого, основные функции должны быть обеспечены из небольшого, совместимого с компилятором интерфейса, который может быть скрыт позже с помощью удобного уровня, который компилируется с клиентским кодом.

Сложным аспектом библиотеки является то, что она имеет чтобы быть расширяемым, чтобы клиенты могли предоставлять свои собственные реализации буфера и потока, но интерфейс базовой библиотеки должен оставаться стабильным после его выпуска. Если вас интересует дополнительная информация, вы можете прочитать об этом в обсуждении темы форума .

Я пытался узнать о проблемах двоичной совместимости между компиляторами, но поскольку я новичок в этой теме, я были бы заинтересованы в комментариях к моему результату. Меня не интересует здесь поведение, определяемое стандартами (структуры, вероятно, не проходят этот тест), только совместимость между mingw и MSVC и , возможно, другими компиляторами, если это удобно.

В частности, будут ли структуры совместимы? Они всегда состоят из указателей на функции, поэтому я не думаю, что заполнение будет проблемой. Кроме того, необходимо ли здесь соглашение stdcall, или cdecl будет работать так же? Могу ли я оставить это значение неопределенным, поскольку оба компилятора по умолчанию будут использовать cdecl? Нужно ли мне? Вот что у меня есть прямо сейчас:

#include 

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);
}

Edit: Проект, для которого это было предназначено, временно приостановлен и, вероятно, нуждается в серьезном переосмыслении, если он когда-нибудь снова откроется. Однако я оставляю вопрос, потому что мне все еще интересно ответить.

7
задан Medo42 16 March 2012 в 10:36
поделиться