5

C# で実装する必要がある C++ で定義したインターフェイスがあります。これについて最善の方法は何ですか?インターフェイス定義で COM をまったく使用したくありません。私が今これを解決した方法は、C++ と C# の 2 つのインターフェイス定義を持つことです。次に、C# インターフェイスを COM サーバーとして公開します。これは、C++ で記述され、C# を呼び出すことができる私のアプリケーションでした。C# だけでなく C++ で実装を定義する必要を回避できる方法はありますか?

4

6 に答える 6

4

マネージ コードに C# の代わりに C++/CLI を使用する場合は、ヘッダー ファイルを介して直接ネイティブ C++ インターフェイス定義を使用できます。これがどれほど簡単かは、インターフェイスの内容によって異なります。最も単純なケースは、C から使用できるものです。

Marcus Heege のExpert C++/CLI: .NET for Visual C++ Programmersを参照してください。.NET でのネイティブ C++ とマネージ C++ の混在に関する多くの役立つ情報があります。

于 2008-09-15T17:33:46.673 に答える
2

Swigは、C# などの他の言語で C++ クラスをラップするための優れたツールです。

于 2008-09-18T03:48:54.727 に答える
1

COMを使いたくないのはなぜですか?

これが私の提案だったでしょう。COM相互運用機能は私にとって非常にうまく機能し、C#でCOMオブジェクトとインターフェイスを使用しました(COMオブジェクトを参照するだけで、ランタイム呼び出し可能ラッパーが自動的に作成されます)。同様に、C#クラスを「COM相互運用機能の登録」としてマークすると、逆の方法で機能します。

于 2008-09-15T17:02:01.290 に答える
1

もう 1 つのアプローチは、「フラットな」C スタイルの API を使用することです。extern "C"偶発的な過負荷を防ぐために使用することもできます。DEF ファイルを使用して、エクスポートされた関数に明示的に名前を付けます。これにより、関数は決して装飾されません (C++ 関数は、エクスポート テーブルのパラメーター タイプのエンコーディングで「装飾」されます)。

x86 では、呼び出し規約に注意してください。おそらく__stdcallorの使用を明示的に宣言することです__cdecl。P/Invoke は主に Windows API を呼び出すために使用されるため、既定値は StdCall ですが、C および C++ の既定値は cdecl です。これは、varargs がサポートされているためです。

最近IRapiStream、.NET が IStream をストレージに変換しようとしているように見えたため、COM インターフェイスをフラット C インターフェイスにラップしましたが、エラーで失敗しましたSTG_E_UNIMPLEMENTEDFUNCTION

于 2008-09-15T23:18:41.710 に答える
1

C++ でインターフェイスを記述し、マクロを使用して、UNIX では標準の cpp ヘッダー ファイルのように、Windows では IDL ファイルのように見えるようにします (これがうまくいかない場合は、いつでも python/ruby スクリプトを記述して、 C++ ヘッダー ファイル)。

IDL をコンパイルして typelib を生成します。TypeLib Importer を使用して、C# のインターフェイス定義を生成し、そこにインターフェイスを実装します。

于 2008-09-15T18:06:54.643 に答える
0

使用している .NET のバージョンについては言及されていませんが、Visual Studio .NET 2003 を使用してうまくいったことは、実際の C++ クラスの単純な実装の周りに薄い C# ラッパーを提供することです。

public __gc class MyClass_Net {
public:
   MyClass_Net()
      :native_ptr_(new MyClass())
   {
   }
   ~MyClass_Net()
   {
      delete native_ptr_;
   }

private:
   MyClass __nogc *native_ptr_;
};

明らかに、Boost shared_ptr を使用したいのですが、V.NET 2003 でうまく動作させることはできませんでした...

メソッドは、ポインターを介して基になる C++ メソッドに単純に転送されます。メソッドの引数を変換する必要がある場合があります。たとえば、文字列を受け取る C++ メソッドを呼び出すには、C# メソッドはおそらく System.String (Managed C++ では System::String) を受け取る必要があります。これを行うには、System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi() を使用する必要があります。

このアプローチの利点の 1 つは、Managed C++ が .NET 言語であるため、アクセサーをプロパティ (__property) として公開できることです。C# のように、属性を公開することもできます。

于 2008-09-15T21:01:28.063 に答える