C neden C ++ 'un yetersiz kaldığı durumlarda' dilleri 'sağlıyor?


60

Son zamanlarda C ++ 'ın C ++' ı ne zaman kullanacağını merak ediyordum . Neyse ki biri beni çoktan dövdü ve biraz zaman alsa da, bu soruya verilen tüm cevapları ve yorumları sindirebildim.

Bununla birlikte, bu gönderideki bir öğe, herhangi bir örnek, doğrulama veya açıklama olmadan tekrar tekrar ele alınmaya devam ediyor:

"C kodu, kitaplığınız için birden çok dilde bağlantı olmasını istediğinizde işe yarar"

Bu bir şifre. Birkaç kişinin C ++ 'da çoklu dil bağlantılarının mümkün olduğunu belirttiğine dikkat etmeliyim (bazı externişlevler aracılığıyla ), ancak yine de, eğer bu yazıyı bütünüyle okursanız, C'nin taşınabilirlik / dil bağlama için ideal olduğu açıktır. Sorum şu: neden?

Birisi lütfen kütüphaneleri C'ye yazmanın neden başka dillerde daha kolay ciltleme ve / veya taşınabilirlik sağladığına dair somut nedenler verebilir mi?


6
Çoğunlukla tarihi ve sosyal nedenlerden dolayı. Çoğu dil uygulaması ve çalışma zamanı sistemi C'nin üzerinde inşa edilmiştir. Örneğin, Ocaml, SBCL, Haskell çalışma zamanları C olarak kodlanmıştır (ve C ++ 'da yeniden kodlanarak fazla kazanılmaz)
Basile Starynkevitch

8
Uygulamada, gerçek C ++ kitaplıklarının (Qt düşünün) bu çalışma sürelerine yapıştırılması acı vericidir.
Basile Starynkevitch,

3
@Basile: Qt gerçek bir C ++ kütüphanesi değil. Ayrıca, daha acı veren kütüphaneler için bile, sadece acı vericidir, çünkü aslında yararlı bir anlambilim ifade ederler.
DeadMG


2
Don Box tarafından Temel COM okuyun. C ++ 'da ABI oluşturma işlemini açıklar. COM, Microsoft’un bir ABI yaratma şekliydi. yani COM C ++ kütüphaneleri C veya VB'den veya diğer dillerden kullanılabilir.
user93353

Yanıtlar:


69

C, çok, çok daha basit bir arayüze sahiptir ve bir kaynak kod arayüzünü ikili bir arayüze dönüştürmek için kuralları, bağlanması gereken harici arayüzler oluşturmanın, sağlam bir şekilde yapılması için yeterince kolaydır. Öte yandan, C ++, inanılmaz derecede karmaşık bir arayüze sahiptir ve ABI bağlanmasıyla ilgili kurallar, ne resmi olarak ne de pratikte standardize edilmemiştir. Bu, herhangi bir platform için herhangi bir dilin hemen hemen herhangi bir derleyicinin harici bir C arabirimine bağlanabileceğini ve tam olarak ne bekleyeceğini bildiği anlamına gelir, ancak bir C ++ arabiriminde, esasen imkansız çünkü kurallar hangi derleyiciye, hangi sürüme ve hangi sürüme bağlı olarak değişir? platform C ++ kodu ile inşa edilmiştir.

C'de de standart bir ikili dil uygulama kuralları yoktur, ancak bu bir basitlik sırasıdır ve pratikte derleyiciler aynı kuralları kullanır. C ++ kodunu hata ayıklamayı zorlaştırmanın başka bir nedeni de yukarıda belirtilen karmaşık dilbilgisidir, çünkü hata ayıklayıcılar çoğu zaman birçok dil özelliği ile başa çıkamazlar (şablonlara kesme noktaları yerleştirin, veri görüntüleme pencerelerinde ayrıştırıcı işaretçi komutları, vb.).

Standart bir ABI (uygulama ikili arayüzü) olmayışı başka bir sonuç doğurur - C ++ arayüzünü diğer takımlara / müşterilere göndermeyi pratik yapmaz çünkü kullanıcı kodu aynı araçlarla derlenmedikçe ve seçenek oluşturmadıkça çalışmaz. Bu problemin başka bir kaynağını daha önce görmüştük - derleme zamanı enkapsülasyonu olmadığı için ikili arayüzlerin dengesizliği.

- Arızalı C ++


4
C ++ 'da uygulanan C benzeri bir API tanımlamak mümkün olsa da ( extern "C"C ++ tarafından sağlanan özelliklere karşı dengelenmesi gereken daha fazla ek çalışma olduğunu da belirtmelisiniz)
jhominal

5
C ++ ABI, C ++ kütüphanelerinin kolayca ihraç edilebileceği soru bağlamında önemsizdir extern "C".
DeadMG

12
@jhominal: C arayüzünde tanımlamanız çok daha iyi, C arayüzünü tanımlamanız ve sonra C yi uygulamanız gerekir, oysa C ++ 'da C arayüzünü tanımlamanız ve sonra uygulamanız gerekmiyor Hangi dilde uygularsanız kullanın, yine de bir C arayüzü tanımlamanız gerekir - bu elbette C ++ 'da olduğu gibi C veya C bağlarını ortaya çıkarabilecek başka bir dilde de geçerlidir.
DeadMG

9
Bu FQA pervanesinin bağlantısına bir feragatname eklemek mümkün müdür?
Martin Ba,

2
@DocBrown: Bana göre soru C dili bağları ve C ++ dili bağları hakkında.
Mason Wheeler

32

Başka bir dilin konuşucusu ile iletişim kurmaya çalışıyorsanız, pidgin Shakespearean English'ten daha kolaydır.

C'nin kavramları - işlev çağrıları, işaretçiler, NULL sonlandırılmış dizeler - çok basittir, böylece diğer diller bunları C işlevlerini çağırmak için yeterince iyi uygulayabilir. Tarihsel nedenlerden ötürü, C işlevini çağırma işlevini daha da kolaylaştıran birçok başka dil C dilinde uygulanmaktadır.

C ++ oldukça fazla şey ekler - kalıtım ve değişkenler ve erişim değiştiricileri içeren sınıflar; İstisnalar, istifin çözülmesi ve kontrol akışının değiştirilmesi ile; şablonları. Bütün bunlar diğer dillerin C ++ bağlarını kullanmalarını zorlaştırıyor: en iyi ihtimalle uygulamak için daha fazla "yapıştırıcı" ya da birlikte çalışabilirlik kodu var ve en kötüsü de kavramları doğrudan çevirmiyorlar (sınıf modelleri, istisnaların ele alınması, vb.). Özellikle şablonları için, sadece bunları tipik olarak, bir C ++, bir derleme adımını gerektirir (başlatmasını) kullanılarak büyük ölçüde diğer ortamlarından bunları kullanarak karmaşık hale getirir.

Bunların hepsiyle birlikte, C ++ kitaplığından başka dillere bağlanma zorluğunu abartmak mümkündür:

  • Çalışmaya istekliysen, C ++ bağları C kadar uyumlu olabilir. @DeadMG'nin belirttiği gibi, C ++ destekliyor extern "C", böylece C tarzı dil bağlarını (basit ve tüm C bağlarının uyumluluğu ile birlikte) bir C ++ kitaplığından (C ++ 'a özgü herhangi bir işlev gösteremezsiniz) .
  • C ++ dil bağlarına yönelik diğer bir yaygın itiraz, C ++ için ABI istikrarının olmamasıdır, ancak bu da abartılmıştır; C ++ ABI'ler, C ABI'lerden daha az standartlaştırılmıştır, ancak standartlar ve fiili standartlar mevcuttur ( OS X'te de kullanılan Itanium C ++ ABI ; GCC'nin Linux için fiili standardı ). Windows daha kötü, ancak Windows'ta bile bir Visual C ++ sürümünde kalmak iyi çalışmalı.

1
C ++ kütüphanesinden başka bir dile bağlanma ile ilgili diğer sorun , diğer dilin C dilinde uygulanmasını gerektirebileceğidir. Veya (.NET) P / Invoke veya (python) ctypes gibi bir şeye sahip olan diller için C ++ ABI kullanmak için hiçbir araç sağlamayabilir .
Random832

6
@ Random832: C ++ tarafı C arayüzünü sunabileceği zaman tamamen ilgisizdir. Bir C bağlaması sunmak için bağlamayı C içinde uygulamanız gerekmez.
DeadMG

21

C hala etrafındaki en eski dillerden biri. ABI basittir ve günümüzde kullanımda olan hemen hemen her işletim sistemi içinde yazılmıştır . Bu işletim sistemlerinden bazıları, örneğin C # /. NET’te ya da en üstte ne olursa olsun, bazı şeyler eklemiş olsalar da, aşağıdan C’ye çok dik

Bu , işletim sisteminin sağladığı işlevselliği kullanmak için, hemen hemen her programlama dilinin, C kütüphaneleriyle bir şekilde bir arayüz kurmaya ihtiyacı olduğu anlamına gelir . Perl, Java, C ++, hepsi doğal olarak "C" konuşmanın yollarını sunar, çünkü var olan her tekerleği yeniden icat etmek istemiyorlardı.

Bu, C'yi programlama dillerinin Latince'si yapar. (Bu metafordan önce kaç yıl internet "progamming dillerinin İngilizcesi" olmalı?)


Kütüphanenizi C dilinde yazarken, ücretsiz olarak C uyumlu bir arabirim elde edersiniz. Eğer C ++ kütüphanenizi yazıyorsanız, sen yapabilirsiniz aracılığıyla, C bağlamaları olsun extern "C"bahsettiğin gibi bildirimleri.

Bununla birlikte , bu bağlantıları yalnızca C ile ifade edilebilen işlevler için elde edebilirsiniz .

Yani kütüphane API'nizden yararlanamıyor ...

  • şablonlar,
  • sınıflar,
  • istisnalar
  • herhangi bir nesneyi alan veya getiren fonksiyonlar .

Basit bir örnek olarak, dışa aktarılan işlevlerinizin (veya bu konuda) yerine dizileri ( ) almasını ve döndürmesini sağlamanız gerekir .[]std::vectorstd::string

Bu nedenle, yalnızca C ++ 'nın kütüphanenizin müşterilerine sunacağı iyi şeylerden hiçbirini sağlayamazsınız, aynı zamanda kütüphane API'nizi C ++' dan "C uyumlu" ( ) 'ya çevirmek için ek çaba sarf etmeniz gerekir extern "C".

Nokta nedeni budur olabilir C kütüphane uygulanması için daha iyi bir seçim olduğunu yapılabilir. Şahsen, C ++ 'ın faydalarının hala bir extern "C"API için gereken çabadan daha ağır olduğunu düşünüyorum , ama bu sadece benim.


Windows kendini .NET etrafında kurmaya çalışıyor gibi görünüyor, Android Java ( bazı API'ler için bir uygulama detayı olarak C ) ve iOS / OSX de Objective-C civarında.
user253751

1
İngilizce zaten programlama dünyasında baskın bir dildir. Diğer mesleklerden daha baskın.
Siyuan Ren,

3
@ immibis: Windows, Linux / Android ve BSD / OSX, C dilinde yazılmış, hepsi (ve için) C ile yazılan arabirimlerle yazılmış tüm çekirdeklerdir. NET C aramaları, Python C aramaları, Objective-C C aramaları gerektirir. Bunların hiçbiri C ++ çağrısına ihtiyaç duymuyor , bu benim yapmaya çalıştığım nokta.
DevSolar

@DevSolar Android'in birçok içeriği yerel olarak Java dilinde yazılmıştır ve JNI kullanmaz (Java kodunu C konumundan çağırmak için "geriye doğru kullanabilirsiniz", ancak bu, yerel Java olduğunu doğrular). İOS / OSX ile ilgili deneyim yok ancak bunların Objective-C ile aynı olduğunu duydum.
user253751

3
@immibis: Ama bunu sen, bir işletim sisteminin çekirdeğine ve bunun userspace arasındaki farkı bilmiyor musunuz? Ciddi bir şekilde Java kullanıcı alanının, Android'i masaüstümde çalışan Linux çekirdeğinden ziyade C tarzı sistem çağrılarıyla Linux çekirdeği haline getirdiğinden şüpheliyim. Ayrıca çekirdekte veya ara yazılımda Java kullandıklarından da şüpheliyim. Aslında orada C kullandıklarını biliyorum . Tavuk yumurtası sorunu, tam tersi. Daha önce C'de yapıldı ve bu yüzden hala C'de yapmak çok daha kolay .
DevSolar

6

Diğer cevapların daha önce verdiği ayrıntıları bırakmak:

Bu kadar çok dilin C bağlantısı sağlaması nedeni, tüm * nix ve Windows işletim sistemlerinin OS API'lerinin çoğunu bir C arayüzü aracılığıyla göstermesidir. Bu nedenle, dil uygulamasının halihazırda büyük Oses'lerde çalışabilmesi için C ile etkileşime geçmesi gerekiyor. Bu nedenle, dilin kendisinden herhangi bir C arayüzü ile doğrudan iletişim kurmayı teklif etmek de kolaydır.


5

Hiçbir sebep yoktur. Anlatmaya çalıştığınız anlambilim temelde C-uyumlu ve şablonlar gibi bir şey değilse, uygulama C'ye yazılmışsa daha kolay bağlanmanız için hiçbir neden yoktur. Aslında, bir C arayüzünün olabileceği tanımı gereği başka bir dilde bir uygulama da dahil olmak üzere ikili sözleşmeyi karşılayabilecek herhangi bir uygulama tarafından doldurulur. Bu şekilde çalışabilen C ikili sözleşmelerini uygulayabilen C ++ dışındaki diller vardır.

Gerçekten kaynayan şey, dinazor çağında kalmak için çaresizce herhangi bir sebep seçmeye çalışan, gerçekten yararlı bir semantik veya özelliğe sahip yeni diller veya fikirler öğrenmek istemeyen insanlardır.


4
Bence haklısınız ve hakaretçiler bu soruyu yanlış anladılar, ancak aslında cevabınız bu olası yanlış anlaşılmayı vurgulamayı özlüyor: soru, "C arayüzlü bir kütüphane" ile "C ++ arayüzlü bir kütüphane" ile ilgili değil. "tamamen C dilinde yazılmış bir kütüphane" vs. "C ++ ile yazılmış bir C arayüzü olan bir kütüphane".
Doktor Brown

@Snowman: Sorunlu C ++ bağlarına sahip olmak, C bağlarını açığa çıkarmada herhangi bir sorunla kesinlikle ilgisi yoktur.
DeadMG

2
Yani yararlı semantik ve özelliklere sahip bir dil seçip daha sonra bunları bir C arayüzüne çevirmeye zorlayacaksınız? Sınıflar ve şablonlar önlenebilirken (ancak neden ilk olarak C ++ kullandığınızı da sorgulayabilirsiniz), C bağlama ile çalışan her işlev, C koduna girmelerine izin vermek yerine istisnaları yakalamak zorundadır. C-uyumlu kitaplığınızı kullanan herhangi birinin artık C ++ 'un ABI çatışması ve kütüphane uyumsuzluğunun yanı sıra C ++' un ABI çatışması ve kütüphane uyumsuzluğu ile de uğraşması gerektiğinden bahsetmiyoruz.
prosfilaes

2
@prosfilaes: İstisnaları, geri dönüş kodlarına dönüştürmek önemsizdir. Sınıfları kullanmaktan kaçınmanıza gerek yoktur çünkü bunlar kolayca bir C API'ye indirgenebilir ve uygulamalarınızda şablon kullanmaktan kaçınmanız gerekmez. Ve kullanıcılarınız kaynaktan kurmazlarsa C ++ ABI çatışmaları hakkında hiçbir şey vermek zorunda kalmazlar; bu durumda, ne olursa olsun, kaynak dille uğraşmanız gerekir.
DeadMG

4
C ++ 'ın C API'sı olan bir kütüphane yazması gerekmediği için değil, C'yi dinazor olmak dışında kullanmanın iyi nedenleri olduğu için not aldım. X dilinde bir API için yazıyorsanız, C, FORTRAN, COBOL, BLISS veya Java dillerinde, her zaman o dilde yazmanın daha kolay, daha kolay ve daha doğru olacağına, ardından meraklılara yazacağınız bir zamana sahip olun. , daha eğlenceli bir dil ve iki arayüz.
prosfilaes

2

Başka bir dille etkileşime girdiğinde iki ana eksen vardır:

  • Arayüzün taşıyabileceği kavramlar: sadece değerler? Referanslar? jenerik?
  • Arayüzün “ikili dosyalar” da (ABI adı verilen) nasıl kullanıldığı

C'nin bu iki cephede C ++ 'a göre avantajı var:

  • C sadece diğer dillerin çoğunda görünen çoğunlukla basit kavramlara sahiptir 1
  • C ikili dosyalarının ABI'sine OS 2 tarafından karar verilir.

Şimdi, neden çoğu dilde C'ninkine benzer bir kavram dizisi var? Neden "basit" veya "önceden var"? önemli değil, mesele onlar.

Aksine, C ++ 'nın karmaşık kavramları vardır ve ABI'ye her derleyici tarafından karar verilir (birçoğu Windows hariç Itanimum ABI'ye uymaktadır). Aslında Herb Sutter tarafından işletim sistemlerinde bu sorunu kısmen ele almak için C ++ ABI (işletim sistemi bazında) düzeltme yapma önerisi vardı. Ayrıca, tek bir C ++ FFI mümkün olduğuna dikkat etmelidir D o çalışıyor 3 .

1 Değişkenler ( ...) dışında , bunlar basit değildir

2 C standart bir ABI'ye sahip mi?

3 D - Legacy C ++ koduna arabirim


0

Temel olarak ABI standardizasyonu ile ilgilidir. Ne C ne de C ++, diğer dillerin yazılmış ikili dosyalar arasında arayüz oluşturmak için kullanabileceği standart bir ABI'ye sahip olmasa da, C fiili bir standart haline geldi, herkes bunu biliyor ve herkes, dilin ilgili olduğu gibi basit, aynı kuralları kullanabilir türleri ve işlev çağrıları.

C ++ standart bir ABI'ye sahip olabilir, ancak Stroustrup birine ihtiyaç duymadığını söyledi. Ayrıca derleyici yazarlardan mutabakata varmanın zor olacağını da belirtti (C ++ standart komitesinin mevcut olanlara benzer bir ABI yayınlayacağından şüpheliyim.) Zaten derleyicilerinin eski sürümleriyle oluşturulmuş - bir kaç kütüphaneyi yeni bir Sun derleyicisiyle yeniden derlediğimi ve eskisiyle çalışamadıklarını tespit ettiğimi hatırlıyorum)

Bazı şirketlerin standart bir ABI kullanmaya başladıklarını, Microsoft'un bu prosedüre 90'lı yıllarda COM yöntemiyle başladığını ve bugün bunu WinRT ABI’de (bu, ilgili diğer WinRT ile karıştırılmaması için) rafine ettiklerini not edersiniz. C # ile yazılmış programların C veya C ++ ile yazılmış kütüphanelerle iletişim kurmasına izin veren bir tablo işletim sistemi türüne) (yani, Microsoft’un kendi işletim sistemi katmanı C ++ ile yazılmıştır, WinRT kullanılarak gösterilir ve herhangi bir işletim sistemi çalışma zamanı rutini çağırdığında C # uygulamaları tarafından tüketilir)

Bir standart organı bu durumu düzeltip düzelmedikçe, kimsenin yapabileceği pek bir şey yoktur. Microsoft, açıkça değeri görüyor ve platformları için sorunu çözmek için adımlar attı.

Yani cevap C gerçekten vermez dil bağlanmaları sağlayın. Ne olursa olsun hiç kimsenin dinlemediği ve tüketmediği anlaşılıyor.


-2

Tüm cevaplar asıl problemin dışında kalıyor: C ++ derleme "isim yönetimi" işlevini tanıtıyor, bu yüzden ikili dosyalar "basit" fonksiyon çağrıları ile uyumlu değil.

Tüm ABI işleri, standardize etme çabasından biraz daha fazlasıdır.

Genel olarak, C ++ düz yapışmış olsanız bile, farklı derleyicilerle derlenmiş işlevleri çapraz bağlayabileceğiniz garanti edilmez. Daha önce uyumsuz olduklarından emindi , ancak bugünlerde standardizasyon sürünüyor;)

OTOH C, tam olarak "yüksek seviye bir montaj" olarak tasarlandı ve her türlü kolay arayüze izin verdi. Çapraz dil beğenisine daha uygun olması şaşırtıcı olmamalıdır.

Not: Orijinal C ++ derleyicisi (cfront) aslında derlenmesi gereken C kaynağını üretti, tam olarak "başlık altında" derleme üreten gcc gibi.

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.