Подтвердить что ты не робот

Совместное использование перечисления из С#, С++/CLI и С++

У меня есть библиотека, состоящая из трех частей. Сначала это родной С++, который обеспечивает фактическую функциональность. Второй - это оболочка/адаптер С++/CLI для библиотеки С++, чтобы упростить переход С# на С++. Наконец, у меня есть библиотека С#, которая вызывает библиотеку С++ через адаптер С++/CLI.

Прямо сейчас у меня есть два набора параллельных определений enum, один из которых хранится в .cs файле, а другой - в .h файле. Это создает двойную проблему:

  • У меня есть двойное обслуживание. Я должен всегда синхронизировать изменения перечисления в обоих расположениях файлов.
  • Пространство имен, используемое обе перечислениями, должно быть идентичным, но оболочка С++/CLI, которая просматривает оба набора перечислений и переводит между ними, несет конфликт имен.

Сейчас я не уверен, что такое решение this или что решит проблемы как. Мысли?

4b9b3361

Ответ 1

Просто поместите свою директиву #include "Enum.cs" во внешнее пространство имен, чтобы разрешить столкновение имен.

EDIT: вариант, предложенный Brent, заключается в использовании #define для замены одного из пространств имен (или даже самого имени перечисления), объявленного в файле .cs. Это также предотвращает столкновение имен, не делая иерархию пространства имен глубже.

Ответ 2

Даже если вы включаете перечисление С# в свой собственный С++ (как показано в первая ссылка), обе перечисления не являются "одинаковыми", перечисление С++ - это не что иное, как список именованных целых чисел, а перечисление С# - из Enum. Как следствие, вы получаете столкновение в С++/CLI при попытке использовать их оба.

Возможное решение - использовать препроцессор, чтобы ваша сборка С++/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,
    };
}

В коде С++/CLI сделайте такое включение:

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

Это дает вам возможность различать эти два вида перечислений EnumShare::MyEnum или EnumShareManaged::MyEnum в вашем коде С++/CLI.

EDIT: только что нашел этот SO-сообщение, показывающий правильный способ бросить между неуправляемыми и управляемыми перечислениями, это, безусловно, будет работать и здесь. Например, в С++/CLI переход от управляемого к неуправляемому перечислению может быть выполнен следующим образом:

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

Ответ 3

Рассмотрим программу создания генератора кода, которая считывает собственный файл h файла с перечислениями и генерирует еще один h файл, преобразуя enum в класс переименования С++/CLI. Такой генератор кода может использоваться в проекте С++/CLI на этапе пользовательской сборки, создавая требуемые перечисления CLI.

Я использую этот подход для создания собственных классов-оболочек для получения функций Enum:: GetNames и Enum:: GetName в неуправляемом С++.