7

私は、そのユーザー(同じプロセスに存在する他のライブラリ)がデータバッファーとストリームを交換できるようにするライブラリに取り組んでいます。ライブラリは、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);
}

編集:これが意図されていたプロジェクトはしばらくの間保留されており、再び棚上げされない場合はおそらく多くの再考が必要です。私はまだ答えに興味があるので、私は質問を残しています。

4

1 に答える 1

3

はい、互換性があります。それがsの美しさstructです。パディングの問題を導入しない限り(正しく指摘したように、ここでは実際には当てはまりません)、またはC ++で、structコンパイラ固有のvtableレイアウトになる機能をsに追加します。常に互換性があります。

また、Windowsヘッダーから、COMインターフェイスのC宣言がstructsを使用するのとほぼ同じ方法で使用されることに気付くでしょう。

補足:SharedStreamInterface::destroyメンバーは、そのようなストリームを「作成」するものもあるかどうかという質問をします。あなたもそれを共有したいかもしれません。しかし、あなたのマイレージは変わるかもしれません...

呼び出し規約の質問に関しては、両方とも__cdeclバイナリ間で機能する__stdcall はず__stdcallですが、私は常に別の理由で好むでしょう:それはより多くの「言語」(つまりツール)と互換性があり__cdeclます。

スタイルの場合:Windowsヘッダー#defineと同様に、aを使用して呼び出し規約を明示的に宣言します(実行する場合と同様) 。WINAPI

于 2012-03-29T01:54:22.293 に答える