16

ライブラリ (libfoo と呼びましょう) を準備するとき、次のようなジレンマに直面していることに気付きます: C ラッパーを使用して C++ ライブラリとして記述しますか?

namespace Foo {
  class Bar {
    ...
  };
}

/* Separate C header. #ifdef __cplusplus omitted for brevity. */
extern "C" {
  typedef void *FooBar;
  FooBar* foo_bar_new() { return new Foo::Bar; }
  void foo_bar_delete(FooBar *bar) { delete bar; }
}

それとも、C++ ラッパーを使用して C ライブラリとして記述した方がよいでしょうか。

/* foo/bar.h. Again, #ifdef __cplusplus stuff omitted. */

typedef struct {
  /* ... */
} FooBar;

void foo_bar_init(FooBar *self) { /* ... */ }
void foo_bar_deinit(FooBar *self) { /* ... */ }

/* foo/bar.hpp */

namespace Foo {
  class Bar {
    /* ... */
    FooBar self;
  }

  Bar::Bar() {
    foo_bar_init(&self);
  }

  Bar::~Bar() {
    foo_bar_deinit(&self);
  }
}

どちらが好きですか、なぜですか? 私は後者を好みます。これは、私の C 関数で誤って例外が発生することを心配する必要がないことを意味するからです。また、言語としては C がより小さな意味論的地雷原であると感じているため、C を好みます。他の人はどう思いますか?

編集:非常に多くの良い答え。皆さんありがとう。1つしか受け入れられないのは残念です。

4

9 に答える 9

19

小さなポイント:

C ライブラリを作成する場合、C、C++ (ラッパーを使用)、および Python、バインディングを使用する Java などの他の多くの言語など、どこでも役立ちます。最も重要なのは、C ランタイムのみを必要とすることです。

C++ ラッパーを作成する場合、C ラッパーも作成する必要がありますが、考えているほど単純ではありません。たとえば、次のようになります。

c_api.h:

extern "C" {
  typedef void *Foo;
  Foo create_foo();
}

c_api.cpp:

void *create_foo() 
{
    return new foo::Foo();
}

なにが問題ですか?投げるかもしれません!Cにはスタック巻き戻しのセマンティクスがないため、プログラムはクラッシュします。したがって、次のようなものが必要です。

void *create_foo() 
{
    try {
       return new foo::Foo();
    }
    catch(...) { return 0; }
}

そして、これはすべてのC++ api 関数に対してです。

したがって、C ライブラリを作成し、別のC++ ラッパーを提供することは、より良い解決策だと思います。

また、C++ ランタイム ライブラリとのリンクも必要ありません。

于 2010-10-12T07:37:31.887 に答える
9

ライブラリを書きたい言語でライブラリを書きます。技術的には、どちらの方法でラップするかは問題ではありません。一部の C プロジェクトは C 以外のライブラリを除外することを目指している場合がありますが、C++ プロジェクトが C で記述されたライブラリを除外するのは奇妙ですが、それは主に実用的なものよりも哲学的な異議です。

C++ ラッパーで C をラップすると、ラッパーが若干大きくなる可能性がありますが、C プログラマーには受け入れられやすくなります。

バイナリを配布する場合は、C の単純さが有利であることに注意してください。

于 2010-10-12T07:05:55.350 に答える
5

C で書くのが好きなら、なぜ C++ ラッパーが必要なのですか? C++ クライアントは、C スタイルの API インターフェイスを使用できます。一方、C++ を好む場合は、C クライアント用の C ラッパーが必要です。

于 2010-10-12T07:07:16.823 に答える
4

lib を (ソース コードを出荷する代わりに) バイナリ + ヘッダーとして配布する必要がある場合は、C API の方がより普遍的にリンク可能であることがわかります。C は通常、どのプラットフォームでも最小の共通 A​​PI であるためです。

これが、私が過去 10 年間に行った API を必要とするプロジェクトのために、インライン C++ ラッパーを使用して C APIを作成する必要があった理由です。プログラムはすべて C++ で書かれていたため、別のラッピング C++ APIを配置するために、 C++ コードの周りに C ラッパー APIを作成する必要がありました。

于 2010-10-12T07:26:21.057 に答える
3

リンク時の最適化なしでコンパイルすると仮定すると、C コンパイラは C++ 呼び出しを処理する方法がわからないため、ラッパー関数をインライン化できませんが、C++ コンパイラは C 呼び出しを簡単にインライン化できます。

したがって、その逆ではなく、C ライブラリの C++ ラッパーを作成することをお勧めします。

于 2010-10-12T07:27:01.273 に答える
2

個人的には、C++ で記述してから、ラッパーを使用して C インターフェイスを公開することを好みます。主な理由は、適切な OO 言語で書きたいからです。オブジェクト指向の C ラッパーも使用します。この投稿で概説したように、この投稿で C から OO C++ を呼び出すために必要なことについてかなり詳細な説明を書きましたオブジェクト指向 C++ コード用の C ラッパー API の開発

于 2010-10-12T09:01:29.253 に答える
2

また、ライブラリで何を使用する予定かにも大きく依存します。他の C++ ライブラリから大きなメリットが得られる場合は、C++ を使用してください。

また、ライブラリが非常に大きくなる場合 (内部的に、必ずしも API に関してではない)、C++ で実装する方が簡単であると主張することもできます。(それは私の好みではありません。私は C を好みますが、C++ を断言する人もいます。)

また、C++ では例外サポートのためにオペレーティング システムを必要とするランタイムが使用されることにも注意してください。

ライブラリがオペレーティング システムの基盤として使用されるか、またはオペレーティング システムのない環境で使用されることを想定している場合は、例外サポートを無効にする方法を知っている必要があり、多くの (すべて?) STL を回避し、独自のものを提供する必要があります。アロケータとデアロケータ。不可能ではありませんが、自分が何をしているのかを正確に知る必要があります。

Cは、これらの低レベルの種類のものにより適しています。

于 2010-10-12T08:30:15.427 に答える
2

私は個人的には C++ を使用することを好み、それを C にラップします。ライブラリを C で書くことに抵抗がない場合は、C++ 用にラップしてください。

例外について: C 用にラップされたすべての関数でそれらをキャッチし、それらのエラー コードを返すことができます。他のライブラリによってスローされたものは、別のものに変換できますが、とにかく早くキャッ​​チする必要があります。

于 2010-10-12T07:08:10.087 に答える
2

ライブラリを C で書くことに慣れている場合は、C で書いてください。Cライブラリとして移植性が高くなり、前述のように例外の問題はありません。C++ ライブラリから始めて C でラップすることは一般的ではありません。

于 2010-10-12T07:10:59.503 に答える