web-dev-qa-db-ja.com

C#、C ++ / CLI、およびC ++からの列挙型の共有

私は3つの部分からなるライブラリを持っています。 1つはネイティブC++で、実際の機能を提供します。 2つ目は、C#からC++への移行を簡素化するための、C++ライブラリ用のC++/CLIラッパー/アダプターです。最後に、C++/CLIアダプターを介してC++ライブラリーを呼び出すC#ライブラリーがあります。

現在、2セットの並列列挙型定義があります。1つは.csファイルに保存され、もう1つは.hファイルに保存されています。これには二重の問題があります。

  1. デュアルメンテナンスがあります。両方のファイルの場所で列挙型の変更を常に同期する必要があります。
  2. 両方の列挙型で使用される名前空間は同一である必要がありますが、両方の列挙型のセットを表示してそれらの間で変換するC++/CLIラッパーでは、名前の衝突が発生します。

今のところ、thisthatのような解決策が解決するかどうかはわかりません両方の問題。考え?

23
Brent Arias

#include "Enum.cs"ディレクティブを外部名前空間内に配置するだけで、名前の衝突を解決できます。

編集:ブレントによって提案されたバリエーションは、#defineを使用して、.csファイルで宣言された名前空間の1つ(または列挙型名自体)を置き換えることです。これにより、名前空間の階層を深くすることなく、名前の衝突を回避することもできます。

2
Ben Voigt

ネイティブC++にC#列挙型を含めても( 最初のリンク で提案されているように)、両方の列挙型は「同じ」ではなく、C++列挙型は名前付き整数のリストにすぎません。 C#列挙型は列挙型から派生しています。結果として、両方を使用しようとすると、C++/CLIで衝突が発生します。

考えられる解決策は、プリプロセッサを使用して、C++/CLIアセンブリが異なる名前空間の両方の列挙型を認識できるようにすることです。

// shared_enum.h

#undef ENUMKEYWORD
#undef ENUMNAMESPACE

#ifdef MANAGED
#define ENUMKEYWORD public enum class
#define ENUMNAMESPACE EnumShareManaged
#else
#define ENUMKEYWORD enum
#define ENUMNAMESPACE EnumShare
#endif

namespace ENUMNAMESPACE
{
    ENUMKEYWORD MyEnum
    {
        a = 1,
        b = 2,
        c = 3,
    };
}

C++/CLIコードで、次のようにインクルードします。

#undef MANAGED
#include "shared_enum.h"
#define MANAGED
#include "shared_enum.h"

これにより、これら2種類の列挙型を区別できるようになりますEnumShare::MyEnumまたはEnumShareManaged::MyEnum C++/CLIコード内。

編集:見つかったばかり this SO post アンマネージド列挙型とマネージド列挙型の間でキャストする正しい方法を示しています。これは確かにここでも機能します。たとえば、C++/CLI、マネージド列挙型からアンマネージド列挙型への移行は次のように実行できます。

void MyWrapperClass::MyWrapperFunction(EnumShareManaged::MyEnum mx)
{
    EnumShare::MyEnum nx = static_cast<EnumShare::MyEnum>(mx);
    // call a native function "func"
    func(nx);
}
11
Doc Brown

列挙型のネイティブhファイルファイルを読み取り、別のhファイルを生成して、列挙型をC++/CLI列挙型クラスに変換するコードジェネレータープログラムの作成を検討してください。このようなコードジェネレーターは、カスタムビルドステップのC++/CLIプロジェクトで使用して、必要なCLI列挙を生成できます。

このアプローチを使用して、アンマネージC++でEnum :: GetNames関数とEnum :: GetName関数を取得するネイティブラッパークラスを生成します。

3
Alex F