7

Kullanıcılarının (aynı işlemde bulunan diğer kitaplıkların) veri arabelleklerini ve akışlarını değiştirmelerini sağlayan bir kitaplık üzerinde çalışıyorum. Kütüphane hem MSVC hem de mingw kodundan kullanılabilir (daha fazla uyumluluk zarar görmez, ancak kesinlikle gerekli değildir). Bunu başarmak için temel işlevsellik, daha sonra istemci koduyla derlenen bir kolaylık katmanı tarafından gizlenebilen küçük, derleyici uyumlu bir arabirimden sağlanmalıdır.Bu arabirim, MSVC ve mingw arasında ikili uyumlu mu?

Kitaplığın zorlu bir yönü, istemcilerin kendi arabelleklerini ve akış uygulamalarını sağlayabilmeleri için genişletilebilir olması gerektiğidir, ancak çekirdek kitaplığı arabirimi serbest bırakıldıktan sonra kararlı kalmalıdır. Daha fazla arka plan ile ilgileniyorsanız, forum thread discussion numaralı telefondan okuyabilirsiniz.

Derleyiciler arasındaki ikili uyum sorunları hakkında bilgi edinmeye çalıştım, ancak bu konuya yeni başladığımdan beri sonuçla ilgili yorumlarla ilgilenirim. Burada standartlar tanımlanmış davranışla ilgilenmiyorum (yapıları muhtemelen bu testi başarısız), sadece mingw ve MSVC ile ve belki de diğer derleyiciler arasında uyumluluk da mümkündür.

Özellikle, yapılar uyumlu olacak mı? Onlar düzgün fonksiyon imleçler oluşur, bu yüzden doldurma bir sorun olacağını düşünmüyorum. Ayrıca, burada gerekli olan stdcall konvansiyonu mu, yoksa cdecl de mi çalışacak? Her iki derleyici cdecl için varsayılan olacak beri belirtilmemiş bırakabilir miyim? Yapmalımıyım?

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

Edit: İşte şu anda ne var bu şimdi ve muhtemelen bir süre için beklemeye olmuştur içindi proje yine hiç unshelved ise yeniden düşünmek bir çok ihtiyacı var. Yine de sorumu bırakıyorum çünkü hala cevabıyla ilgileniyorum.

+0

MSVC altında neden olarak, conv'ları çağıranlar için koşullu tanımlamalar kullanırım, bunun varsayılan olarak, '_cdecl' için varsayılan olduğunu varsaymak güvenli değildir, çünkü bu, proje ayarları ile kolayca geçersiz kılınabilir. – Necrolis

cevap

3

Evet, uyumlu olacaklar. Bu struct s ile güzellik. Doldurma sorunlarını (doğru bir şekilde işaret ettiğin gibi burada olmayacak) ya da C++ ile struct s işlevselliğini eklemediğiniz sürece, - derleyiciye özgü - vtable düzenleri ile sonuçlanacak her zaman uyumlu ol.

Ayrıca, Windows başlıklarından COM arabirimlerinin C bildirimlerinin, sizin yaptığınız gibi, struct s kullanımını da fark edeceksiniz.

Yan not: SharedStreamInterface::destroy üyesi, böyle bir akışı "oluşturma" seçeneği de olup olmadığı sorusunu yanıtlıyor. Siz numaralı telefonu siz de paylaşmak istersiniz. Ama değişebilir kilometre ... çağrı kuralı sorusuna gelince

, hem __cdecl ve __stdcallikili arasında iş, ancak ben her zaman başka bir nedenle __stdcall tercih ediyorum olmalıdır: daha "dilleri ile uyumlu "(yani araçlar), __cdecl'dan.

Stil için: WINAPI numaralı telefona Windows başlıklarından benzer şekilde (olduğu gibi) çağrı kuralını açıkça bildirmek için #define kullanın.