1. ホーム
  2. c++

[解決済み] オブジェクト指向C++コードのC言語ラッパーAPIの開発

2023-03-31 16:51:07

質問

オブジェクト指向の C++ で書かれた)コアロジックにアクセスするために、既存の C++ API をラップする一連の C API を開発したいと考えています。これは本質的に、私たちの C++ ロジックを他の言語から使用できるようにするための接着剤 API になります。オブジェクト指向C++の周りにCをラップすることに関係する概念を紹介する、良いチュートリアル、書籍、またはベストプラクティスは何ですか?

どのように解決するのですか?

これは手作業で行うのはそれほど難しくありませんが、インターフェイスのサイズに依存します。 私がこれを行ったケースは、純粋な C コード内から C++ ライブラリを使用できるようにするためであり、したがって SWIG はあまり役に立ちませんでした。(SWIG はこれを行うために使用できるかもしれませんが、私は SWIG の第一人者ではなく、それは自明ではないように思えました)。

結局、私たちが行ったのは

  1. すべてのオブジェクトは C で不透明なハンドルで渡されます。
  2. コンストラクタとデストラクタは純粋な関数でラップされています。
  3. メンバ関数は純粋関数である。
  4. 他の組み込み関数は、可能な限り C の同等品にマップされます。

つまり、このようなクラス(C++のヘッダ)です。

class MyClass
{
  public:
  explicit MyClass( std::string & s );
  ~MyClass();
  int doSomething( int j );
}

このようにCのインタフェースにマッピングされます(Cヘッダ)。

struct HMyClass; // An opaque type that we'll use as a handle
typedef struct HMyClass HMyClass;
HMyClass * myStruct_create( const char * s );
void myStruct_destroy( HMyClass * v );
int myStruct_doSomething( HMyClass * v, int i );

インターフェースの実装は次のようになります(C++のソース)。

#include "MyClass.h"

extern "C" 
{
  HMyClass * myStruct_create( const char * s )
  {
    return reinterpret_cast<HMyClass*>( new MyClass( s ) );
  }
  void myStruct_destroy( HMyClass * v )
  {
    delete reinterpret_cast<MyClass*>(v);
  }
  int myStruct_doSomething( HMyClass * v, int i )
  {
    return reinterpret_cast<MyClass*>(v)->doSomething(i);
  }
}

キャストを必要としないように、元のクラスから不透明なハンドルを導出し (これは私の現在のコンパイラではうまくいかなかったようです)。C はクラスをサポートしないので、ハンドルを構造体にする必要があります。

これで基本的なCのインターフェイスができました。もし、例外処理を統合する一つの方法を示すより完全な例が必要なら、githubにある私のコードを試してみてください。 https://gist.github.com/mikeando/5394166

面白いのは、必要な C++ ライブラリをすべて、より大きなライブラリに正しくリンクさせることです。gcc (または clang) の場合、これは g++ を使用して最終的なリンク段階を行うことを意味します。