web-dev-qa-db-ja.com

なぜCはC ++では不十分な言語の「バインディング」を提供するのですか?

私は最近、をC++でCを使用する場合、およびその逆の場合を考えていましたか? 幸いなことに、誰かが すでに私を打ち負かしています しばらくかかりましたが、その質問に対するすべての回答とコメントを要約することができました。

ただし、その投稿の1つの項目は、いかなる種類の例、検証、説明もなく、何度も取り上げられ続けています。

「Cコードは、ライブラリに複数の言語バインディングが必要な場合に適しています」

それは言い換えです。複数の言語バインディングがC++で(一部のextern関数を介して)可能であると指摘する人もいることに注意してください。それでも、その投稿全体を読むと、Cが移植性に最適であることは明らかです/言語バインディング。私の質問は:なぜですか?

誰かがCでライブラリを作成すると、他の言語でのバインディングや移植性が容易になる具体的な理由を教えてもらえますか?

60
smeeb

Cははるかに単純なインターフェイスを備えており、ソースコードインターフェイスをバイナリインターフェイスに変換するための規則は単純であり、バインドする外部インターフェイスの生成は確立された方法で行われます。一方、C++は非常に複雑なインターフェースを備えており、ABIバインディングの規則は、正式にも実際にも標準化されていません。これは、あらゆるプラットフォームのあらゆる言語のほとんどのコンパイラーが外部Cインターフェースにバインドして、何が期待できるかを正確に把握できることを意味しますが、C++インターフェースの場合、ルールはコンパイラー、バージョン、およびバージョンによって異なるため、基本的に不可能です。 C++コードがビルドされたプラットフォーム。

Cでは、標準のバイナリ言語の実装ルールもありませんが、桁違いに単純であり、実際にはコンパイラーは同じルールを使用します。 C++コードのデバッグが困難になるもう1つの理由は、デバッガーが多くの言語機能を処理できないことが多いためです(テンプレートにブレークポイントを配置する、データ表示ウィンドウでポインターキャストコマンドを解析するなど)。

標準のABI(アプリケーションバイナリインターフェイス)がないと、別の結果が生じます。同じツールとビルドオプションでコンパイルしない限り、ユーザーコードは機能しないため、他のチームや顧客へのC++インターフェイスの配布は現実的ではありません。この問題の別の原因はすでに確認済みです-コンパイル時のカプセル化の欠如によるバイナリインターフェイスの不安定性。

- 欠陥のあるC++

69
Mason Wheeler

別の言語の話者とコミュニケーションをとろうとしている場合は、シェークスピア英語より Pidgin の方が簡単です。

Cの概念-関数呼び出し、ポインター、NULLで終了する文字列-は非常に単純なので、他の言語はC関数を呼び出すのに十分なだけ簡単に実装できます。歴史的な理由により、他の多くの言語がCで実装されているため、C関数の呼び出しがさらに簡単になります。

C++は、継承とvtablesとアクセス修飾子を備えたクラスをかなり追加します。例外。スタックの巻き戻しと制御のフローの変更。テンプレート。これらすべてにより、他の言語がC++バインディングを使用することが難しくなります。せいぜい、実装する「接着剤」または相互運用性コードが多く、最悪の場合、概念が直接変換されません(クラスモデルの違い、例外処理のため)。等。)。特にテンプレートの場合、単にテンプレートを使用(インスタンス化)するには、通常、C++コンパイラでのコンパイル手順が必要であり、vastly他の環境からのテンプレートの使用が複雑になります。

以上のことから、C++ライブラリから別の言語へのバインディングを提供することの難しさを誇張することは可能です。

  • C++バインディングは、Cと同じくらい互換性がある場合があります。 @DeadMGが指摘しているように、C++はextern "C"をサポートしているため、Cスタイルライブラリのバインディング(Cバインディングのすべてのシンプルさと互換性を備えたもの)をC++ライブラリからエクスポートできます(制限はありません) C++固有の機能)。
  • C++言語バインディングに対するもう1つの一般的な異論は、C++に対するABIの安定性の欠如ですが、これも誇張されています。 C++ ABIはC ABIほど標準化されていませんが、標準と事実上の標準が存在します(Itanium C++ ABIも使用されます OS Xの場合 ; GCCの事実上の標準 for Linux)。 Windowsの方が悪いですが、Windowsでも 1つのVisual C++バージョン内 を維持すると問題なく動作します。
32
Josh Kelley

Cはまだ最も古い言語の1つです。そのABIは単純で、であり、現在も使用されているほぼすべてのオペレーティングシステムがその中に記述されています。これらのOSの一部には、たとえばC#/。NETやその他の上部、下部には、Cが非常に多く含まれています。

つまり、OSが提供する機能をuseするために、事実上、そこにあるすべてのプログラミング言語には、とにかくCライブラリ。 Perl、Java、C++、それらすべてnatrativeは、「Cと対話する」方法を提供します。なぜなら、彼らはそこにあるすべてのホイールを再発明したくない場合にそうしなければならなかったからです。

これにより、Cはプログラミング言語のラテン語になります。 (そのメタファーが「プログラミング言語の英語」になるまでのインターネットの何年?)


ライブラリをCで記述している場合は、C互換のインターフェースを無料で入手できます(明らかに)。ライブラリをC++で記述している場合、あなたが述べたようにextern "C"宣言を介してcanCバインディングを取得できます。

ただし、これらのバインディングを取得できますonly機能性で表すことができますC

したがって、ライブラリAPIは利用できません...

  • テンプレート、
  • クラス、
  • 例外、
  • すべての関数takeingまたはreturningオブジェクト。

簡単な例の1つとして、[]の代わりに、エクスポートした関数をtakeおよびreturn配列(std::vector)にする必要があります。 (または、std::stringについて)。

したがって、C++がライブラリのクライアントに提供する必要のある優れた機能を提供できないだけでなく、additionalにアクセスして「翻訳する」必要があります。 "C++から" C互換 "へのライブラリAPI(extern "C")。

そのため、ライブラリの実装にはCがより良い選択であるという点couldが指摘されています。個人的には、C++の利点は、extern "C" APIに必要な労力を上回ると思いますが、それは私だけです。

21
DevSolar

他の回答がすでに提供している詳細を省く:

多くの言語がCバインディングを提供する理由は、すべての* nixおよびWindowsオペレーティングシステムがCインターフェイスを介してOS APIのほとんどを公開しているためです。そのため、言語の実装は、主要なOsesで実行できるようにするために、Cとのインターフェースが必要です。したがって、言語自体から任意のCインターフェイスと直接通信することも提供するのは簡単です。

6
Martin Ba

理由はありません。表現しようとしているセマンティクスが基本的にC互換であり、テンプレートのようなものではない場合、実装がCで記述されていれば、簡単にバインドできる理由はありません。実際、ほとんど定義により、C言語のインターフェースは、バイナリ契約を満たすことができる任意の実装(別の言語での実装を含む)によって入力できること。この方法で機能するCバイナリコントラクトを実装できるC++以外の言語があります。

結局のところ、恐竜の時代にとどまる理由を何とかしようと必死に努力している、実際に役立つセマンティクスや機能を備えた新しい言語やアイデアを学びたくない人々です。

5
DeadMG

別の言語とのインターフェースには、2つの主要な軸があります。

  • インターフェースが引き継ぐことができる概念:単なる値?参照?ジェネリック?
  • 「バイナリ」(ABIと呼ばれる)でのインターフェースの実装方法

Cは、これらの2つの面でC++よりも優れています。

  • Cには、ほとんどすべての言語で使用される、ほとんど単純な概念しかありません。1
  • CバイナリのABIはOSによって決定されます2

さて、whyほとんどの言語は、Cよりも同様の概念のセットを持っていますか?それは、「単純」または「既存」のいずれかであるためです。それは問題ではありませんが、ポイントは彼らがそうすることです。

それどころか、C++には複雑な概念があり、ABIは各コンパイラーによって決定されます(多くの場合、Windowsを除いてItanimum ABIに準拠しています)。この問題に部分的に対処するために、OSにC++ ABIを(OSごとに)修正するようにハーブサッターから提案が実際にありました。また、C++ FFIが可能であることに注意してください。Dがそれを試みています。

1 バリアディック(...)、それらは単純ではありません

2 Cには標準のABIがありますか?

DをレガシーC++コードにインターフェースする

2
Matthieu M.

基本的には、ABI標準化に帰着します。 CにもC++にも標準化されたABIはありませんが、他の言語はバイナリの記述間のインターフェースに使用できますが、Cは事実上の標準になり、誰もがそれを知っており、他の誰もが言語に関する同じ単純な規則を使用できますタイプと関数呼び出し。

C++は標準のABIを持つことができますが、Stroustrupはその必要性はないと見ています。彼はまた、コンパイラライターからコンセンサスを得ることは難しいだろうと言っています(C++標準委員会が既存のものと同様のABIを発行し、コンパイラライターがコンパイラの次のバージョンを変更するだけで、バイナリと互換性がない場合があります)とにかく、古いバージョンのコンパイラーでビルドされました-新しいSunコンパイラーでいくつかのライブラリーを再コンパイルしたところ、古いライブラリーで動作しなかったことがわかりました)

一部の企業は標準ABIの使用に移行し、Microsoftはこのプロセスを90年代にCOMで開始し、本日はこれをWinRT ABIに改良しました(参照する他のWinRTと混同しないでください) C#で記述されたプログラムがCまたはC++で記述されたライブラリと通信できるようにするテーブルOSのタイプへ(つまり、Microsoft独自のOSレイヤーはC++で記述され、WinRTを使用して公開され、OSランタイムルーチンを呼び出すときにC#アプリケーションによって使用されます)

標準化団体がこの状況を改善して修正しない限り、誰でもできることは多くありません。マイクロソフトは明らかにその価値を認識しており、プラットフォームに合わせて解決策を講じています。

だから答えは本当にC しない言語バインディングを提供する。誰も聞いたことがないにもかかわらず、それを消費していることが起こります。

0
gbjbaanb