10

今日、同僚と議論していました。彼は、C で DLL を作成すると、どの言語で作成された他のアプリケーションでもその DLL を使用できるようになると主張しました。ただし、その DLL が C++ で記述されている場合、その DLL を使用できるアプリケーションの数は制限されます (おそらく言語の制約のため)。

  1. 彼の言うことは正しいですか。
  2. あらゆる種類の言語で書かれたあらゆる種類のアプリケーションで使用される DLL を作成する場合 (ただし、同じプラットフォーム上にあり、移植性については少し忘れましょう)、C/C++ で作成しますか? また、その理由は何ですか?

この質問がゴリラ対サメの質問ではないことを願っています。ある場合は、閉じてください。

4

3 に答える 3

13

ほとんどの言語は、DLL から C 関数を呼び出す (簡単な) 方法を提供します。C++ ABI (C++ 関数のバイナリ インターフェイス) はベンダー固有であるため、C++ には当てはまりません。

それに加えて、テンプレートや STL などの高度なC++ コンストラクトを使用する C++ DLL とのインターフェイスはほぼ不可能です。

ただし、DLL の内容は C++ で記述できます。インターフェースが C 準拠であることを確認するだけで済みます。これを行うには、インターフェイスで C++ 構造を使用せず、宣言を次のように囲みます。

#ifdef __cpluscplus
extern "C" {
#endif

/* You declarations here */

#ifdef __cpluscplus
}
#endif

... このように、C++ ライブラリを C インターフェイスでラップします。

EDIT : Mats Petersson が書いたように、ラッパーで考えられるすべての C++ 例外を確実に処理することを忘れないでください。

于 2013-05-24T08:08:44.953 に答える
5

1) DLL によって提供される INTERFACE が実際に C++ インターフェイスである場合、はい、他の言語が DLL とインターフェイスするのが (不可能ではないにしても) 難しくなります。

C++ は、C よりもインターフェイスが複雑です。これは、クラスの構造 (this渡されるポインター、仮想関数ポインター/VTABLE レイアウト) および例外処理 (呼び出されたコードが例外が発生したという事実を処理する必要がある場合)がより複雑であるためです。そのためには、コードは、例外をスローしたコードの呼び出しスタックを「巻き戻し」、途中で作成されたオブジェクトを見つけるまで破棄できる必要がありますcatch- それが呼び出しスタックに存在しない場合DLL内で問題が発生します-この巻き戻しはC++標準の一部ではありません。標準は、プロセッサが必要とする/必要以上にC++を実装する必要があるアーキテクチャと機能を制限したくないためです)。DLL 内で例外をキャッチすると、ここでの問題が解決されます。

言い換えれば、コードを呼び出している言語が C++ ではない場合 (およびおそらく同じベンダーから)、呼び出し元の言語が何であれ、C++ を処理する必要があります。これはかなり複雑になる可能性があります。

C++ オブジェクトは、呼び出し元のコードで関連する言語との間で変換する必要があります。C と共通の基本的な型の場合、これは通常問題にはなりませんが、クラス、構造体などは、ローカル言語で互換性のあるものと一致させる必要があります。

一方、AC 関数はインターフェイスが非常に簡単です。引数をスタックに置き、関数を呼び出し、戻り時に引数をクリーンアップします。奇妙なことは何も起こらず、隠し関数パラメーターも、スタックを巻き戻す必要もありません。唯一のわずかな複雑さは、struct(特定のサイズよりも大きい) a を返す関数です。ただし、これは C ではかなり特殊なケースです。C の「オブジェクト」ははるかに単純であり、ほとんどの言語には、基本的な C 言語の型 (しかし、C スタイルstructは依然としていくつかの興味深い問題を引き起こす可能性unionがあり、「巧妙に」使用すると非常に困難になる可能性があります)。

2) 言語の選択は複雑な作業であり、DLL がどのように使用されるか、提供されるインターフェイスの種類、および DLL が別の C++ とインターフェイスしている場合は、DLL 自体がどのインターフェイスに接続する必要があるかに大きく依存します。 DLL (またはその他の C++ コード) の場合、おそらく C++ を使用する必要があります。extern "C"しかし、 for インターフェイス関数を使用して、C インターフェイスを持つ C++ DLL を生成する方法があります(そしてthrows、"C" の壁を越えないようにします。これは間違いなく問題を引き起こすからです)。

結論: 明らかに、インターフェイスを「C++ のみを使用する」ように制限することで、C、Python、または Lisp [おそらく C 関数をかなり簡単に呼び出すことができる] からライブラリを使用する人がいるという点で、さらに複雑になります。ユーザーは C++ コードを C 言語ラッパーでラップする必要があります。はい、これは可能であり、C++ で本当に優れたライブラリが利用可能で、C スタイルのインターフェイスが利用可能な言語に接続したい場合に、かなり定期的に使用されます。これは、DLL のプロデューサーによって提供されないことを除いて、「DLL 内で C から C++ へのインターフェイスを提供する」とほぼ同じソリューションです。

于 2013-05-24T08:41:42.073 に答える
0

各言語には、呼び出し規約、スタックのセットアップなどの独自の特徴があります。言語の境界を越える関数呼び出しを処理しようとするときはいつでも、これに対処する必要があります。コンパイラは通常、さまざまな呼び出し規則をサポートしているため、定義とコンパイルが正しいことを確認する必要があります。そうすれば、任意の言語を使用して他のモジュールと通信できます。ある言語または別の言語から行うのが簡単または困難であるという声明自体は、真実ではありません。

私は自分の仕事に最も適した言語を選択しますが、その逆ではありません。GUI アプリケーションを作成するときは、通常は Java を使用します。これにより、メモリを追跡する代わりにソリューションに集中できるからです。:) パフォーマンスが必要な場合は、C または C++、さらにはアセンブラーを使用するため、言語の選択は、その言語で何をするつもりか、または環境がどのように見えるかによって異なります。

于 2013-05-24T08:07:07.833 に答える