Estoy trabajando en una biblioteca que permite a sus usuarios (otras bibliotecas que residen en el mismo proceso) intercambiar almacenamientos intermedios y flujos de datos. La biblioteca tiene que ser utilizable tanto desde MSVC como desde el código mingw (la mayor compatibilidad no duele, pero no es estrictamente necesaria). Para lograr esto, la funcionalidad central debe proporcionarse desde una pequeña interfaz compatible con el compilador que luego se puede ocultar mediante una capa de conveniencia compilada con el código del cliente.¿Es esta interfaz binaria compatible entre MSVC y mingw?
Un aspecto desafiante de la biblioteca es que debe ser extensible para que los clientes puedan proporcionar sus propias implementaciones de búfer y secuencia, pero la interfaz de la biblioteca central debe permanecer estable una vez que se lance. Si está interesado en más antecedentes, puede leer sobre esto en el forum thread discussion.
He intentado aprender sobre los problemas de compatibilidad binaria entre los compiladores, pero como soy nuevo en este tema, me interesarían los comentarios sobre mi resultado. No estoy interesado en el comportamiento definido por los estándares aquí (las estructuras probablemente fallan en esa prueba), solo en compatibilidad entre mingw y MSVC y quizás otros compiladores si es conveniente.
En particular, ¿las estructuras serán compatibles? Consisten de manera uniforme en indicadores de función, por lo que no creo que el relleno sea un problema. Además, ¿es necesaria aquí la convención estándar o funcionaría igual de bien? ¿Podría dejarlo sin especificar porque ambos compiladores usarán cdecl por defecto? ¿Debería? Aquí es lo que tengo en este momento:
#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);
}
Editar: El proyecto esta era para ha estado en espera desde hace un tiempo y probablemente necesita una gran cantidad de repensar si es cada vez unshelved nuevo. Sin embargo, estoy dejando la pregunta, porque todavía estoy interesado en la respuesta.
Usaría definiciones condicionales para aquellos que llaman convs, porque bajo MSVC, no es seguro suponer que va a '' __cdecl', ya que puede anularse fácilmente con la configuración del proyecto. – Necrolis