سؤال

أنا أعمل على مكتبة تسمح لمستخدميها (المكتبات الأخرى الموجودة في نفس العملية) بتبادل المخازن المؤقتة للبيانات وتدفقاتها.يجب أن تكون المكتبة قابلة للاستخدام من كل من كود 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 يتم استخدام إعلانات C لواجهات COM structبنفس الطريقة التي تفعلها تقريبًا.

ملاحظة جانبية:ال SharedStreamInterface::destroy يطرح العضو السؤال عما إذا كان هناك أيضًا شخص "لإنشاء" مثل هذا الدفق.أنت يمكن تريد مشاركة ذلك أيضا.لكن عدد أميالك قد يتفاوت ...

وأما مسألة اصطلاح الدعوة فكلاهما __cdecl و __stdcall يجب العمل عبر الثنائيات، ولكنني أفضّل دائمًا __stdcall لسبب آخر:وهو متوافق مع المزيد من "اللغات" (أي.أدوات) من __cdecl.

للأسلوب:إستخدم #define للإعلان عن اصطلاح الاتصال بشكل صريح (كما تفعل أنت) على غرار WINAPI من رؤوس ويندوز.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top