C kodunda C ++ kitaplığını kullanma


103

Verileri yönetmek için çeşitli sınıflar sağlayan bir C ++ kitaplığım var. Kütüphanenin kaynak koduna sahibim.

Kitaplığın C kodu ve C ++ kodu ile aynı anda kullanılabilmesi için C işlev çağrılarını desteklemek için C ++ API'yi genişletmek istiyorum.

GNU araç zincirini (gcc, glibc vb.) Kullanıyorum, bu nedenle dil ve mimari desteği bir sorun değil.

Bunun teknik olarak mümkün olmamasının herhangi bir nedeni var mı?

Dikkat etmem gereken herhangi bir sorun var mı?

Bununla ilgili kaynaklar, örnek kodlar ve / veya belgeler var mı?


Öğrendiğim diğer bazı şeyler:

  1. C kodu tarafından kullanılması gereken C ++ başlıklarınızı sarmak için aşağıdakini kullanın.

#ifdef __cplusplus
extern "C" {  
#endif  
//  
// Code goes here ...  
//  
#ifdef __cplusplus  
} // extern "C"  
#endif
  1. "Gerçek" C ++ arayüzlerini, C. tarafından dahil edilmeyen ayrı başlık dosyalarında tutun . PIMPL ilkesini burada düşünün . #ifndef __cplusplus #errorMalzeme kullanmak, herhangi bir çılgınlığı tespit etmeye yardımcı olur.
  2. C kodundaki adlar olarak C ++ tanımlayıcılarına dikkat edin
  3. C ve C ++ derleyicileri arasında boyut olarak değişen numaralandırmalar. GNU araç zincirini kullanıyorsanız muhtemelen bir sorun değildir, ancak yine de dikkatli olun.
  4. Yapılar için aşağıdaki formu takip edin, böylece C'nin kafası karışmaz.

    typedef struct X { ... } X
    
  5. Daha sonra C ++ nesnelerinin etrafından geçmek için işaretçiler kullanın, bunların C'de yapı X olarak bildirilmesi gerekir;

Tüm bunlar, C ++ 'da sihirbaz olan bir arkadaşın nezaketidir.


5
Biraz geç, ancak C ++ için C sarıcı hakkında küçük bir "howto" yazdım: teddy.ch/c++_library_in_c
Teddy

Yanıtlar:


69

Evet, bu kesinlikle mümkün. Aşağıdakilerle işlevleri bildiren C ++ 'da bir arayüz katmanı yazmanız gerekecektir extern "C":

extern "C" int foo(char *bar)
{
    return realFoo(std::string(bar));
}

Daha sonra, çağrıyı C ++ 'da uygulanan işleve foo()iletecek olan C modülünüzden arayacaksınız realFoo().

Veri üyeleri ve yöntemlerle tam bir C ++ sınıfını ortaya çıkarmanız gerekirse, bu basit işlev örneğinden daha fazla iş yapmanız gerekebilir.


Should extern "C"sadece beyanlarına yer (ve tanımlarında) olmak? Çünkü "işlevleri bildiren katmandan" bahsetmiştiniz ama örnek kodunuz da bir tanımdır. Başka bir deyişle, başlık dosyalarına mı yoksa kaynak dosyalarına mı yerleştirmeliyiz? (Veya her ikisine birden mi?)
kyriakosSt

@KyrSt: İşlev bildirimine sahip bir başlık dosyanız varsa, en azından extern "C"oraya koymanız gerekir . Derleyiciniz, tanıma da koymanız gerekip gerekmediğini size söyleyecektir.
Greg Hewgill

23

C ++ FAQ Lite: "C ve C ++ kodu nasıl karıştırılır" .

Bu soruların yanıtlarında bazı sorunlar açıklanmıştır:

  • [32.8] C ++ sınıfındaki bir nesneyi C işlevine / işlevinden nasıl geçirebilirim?
  • [32.9] C işlevim, bir C ++ sınıfının bir nesnesindeki verilere doğrudan erişebilir mi?

12

Ana sorun: C'de istisnalar yakalanamaz. C ++ kodunda bir istisnanın yükselme olasılığı varsa, ya C kodunuzu ya da C ++ sarmalayıcılarınızı çok dikkatli bir şekilde yazın. Tersine, C kodundaki istisna benzeri mekanizmalar (yani, uzun atlama) (çeşitli komut dosyası dillerinde olduğu gibi) yığındaki C ++ nesneleri için yıkıcıları çağırmak için gerekli değildir.


2
Longjump aramaları hakkında harika bir nokta. Bunları doğrudan kullanmasam da, kullandığım test çerçeveleri onları uygular. Akılda tutulması gereken bir şey. Teşekkürler
Misha M

3

C / C ++ kodunu karıştırabilirsiniz. Main () işleviniz C ++ 'da ise, o zaman c işlevlerinizin bildirildiğinden emin olmanız yeterlidir.

extern "C"

Ana değeriniz C ise, statik değişkenler dışında muhtemelen iyisinizdir. Statik değişkenlerinize sahip herhangi bir kurucu, main () startından önce çağrılmalıdır. C ana öğenizse bu olmayacak. Çok fazla statik değişkeniniz var, yapılacak en iyi şey, statik değişkenleri tekillerle değiştirmektir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.