Совместное использование перечисления из С#, С++/CLI и С++
У меня есть библиотека, состоящая из трех частей. Сначала это родной С++, который обеспечивает фактическую функциональность. Второй - это оболочка/адаптер С++/CLI для библиотеки С++, чтобы упростить переход С# на С++. Наконец, у меня есть библиотека С#, которая вызывает библиотеку С++ через адаптер С++/CLI.
Прямо сейчас у меня есть два набора параллельных определений enum, один из которых хранится в .cs файле, а другой - в .h файле. Это создает двойную проблему:
- У меня есть двойное обслуживание. Я должен всегда синхронизировать изменения перечисления в обоих расположениях файлов.
- Пространство имен, используемое обе перечислениями, должно быть идентичным, но оболочка С++/CLI, которая просматривает оба набора перечислений и переводит между ними, несет конфликт имен.
Сейчас я не уверен, что такое решение this или что решит проблемы как. Мысли?
Ответы
Ответ 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 в неуправляемом С++.