Можно ли совместно использовать объявление перечисления между C# и неуправляемым C++?
Вопрос
Есть ли способ совместно использовать определение перечисления между собственным (неуправляемым) C++ и (управляемым) C#?
У меня есть следующее перечисление, используемое в полностью неуправляемом коде:
enum MyEnum { myVal1, myVal2 };
Наше приложение иногда использует управляемый компонент.Этот компонент C# получает значения элементов перечисления в виде целых чисел через управляемую библиотеку взаимодействия C++ (из собственной библиотеки dll).(Библиотека взаимодействия загружается только в том случае, если необходим компонент C#.) Компонент C# продублировал определение перечисления:
public enum MyEnum { myVal1, myVal2 };
Есть ли способ устранить дублирование, не превращая собственную dll C++ в управляемую dll?
Решение
Вы можете использовать один файл .cs и использовать его в обоих проектах. #include
в C++ в файле .cs не должно возникнуть проблем.
Это будет пример файла .cs:
#if !__LINE__
namespace MyNamespace
{
public
#endif
// shared enum for both C, C++ and C#
enum MyEnum { myVal1, myVal2 };
#if !__LINE__
}
#endif
Если вам нужно несколько перечислений в одном файле, вы можете сделать это (хотя вам придется временно определить public как ничто для C/C++):
#if __LINE__
#define public
#else
namespace MyNamespace
{
#endif
public enum MyEnum { MyEnumValue1, MyEnumValue2 };
public enum MyEnum2 { MyEnum2Value1, MyEnum2Value2 };
public enum MyEnum3 { MyEnum3Value1, MyEnum3Value2 };
#if __LINE__
#undef public
#else
}
#endif
Другие советы
Спасибо, что поделился!
Я немного поигрался и нашел способ иметь несколько объявлений перечислений и констант без тонны дополнительных строк :)
// This is a valid C, C++ and C# file :)
#if __LINE__
#define public
#else
namespace MyCSharpNamespace{
#endif
public enum MyConstant { MaxStr = 256 };
public enum MyEnum1{ MyEnum1_A, MyEnum1_B };
public enum MyEnum2{ MyEnum2_A, MyEnum2_B };
#if __LINE__
#undef public
#else
}
#endif
Не забудьте назвать файл *.cs.
Вы можете предоставить библиотеку C# для COM, а затем импортировать библиотеку типов в неуправляемый код — таким образом вы сможете использовать перечисление, определенное в библиотеке C#, в неуправляемой библиотеке.
Неуправляемый C++ и C# живут в двух разных мирах, поэтому нет возможности использовать одно и то же перечисление без изменения библиотеки C++ DLL на управляемую.
И даже в этом случае вам, вероятно, понадобится дублирование в управляемой C++ DLL.
Перечисление C++ во многом похоже на список констант, тогда как перечисление C# наследует класс Enum и, таким образом, предоставляет немало «хитростей».Итак, как вы можете видеть, они очень другой.
Если не имеет значения, является ли собственная DLL C++ собственной или управляемой, я бы превратил ее в управляемую и обернул собственные вызовы внутри управляемого уровня C++.
Таким образом, вы можете иметь дублирование перечисления внутри C++ DLL, а также одновременно избавиться от всего взаимодействия :-)
Раньше у меня была такая же проблема, и я решил ее, используя определения препроцессора.
В неуправляемом коде внутри заголовка, который также может быть включен в управляемую оболочку, поместите элементы перечисления в #define.
Затем в определениях управляемого и неуправляемого перечисления используйте один и тот же #define для обоих случаев.
Перемещение перечислений между управляемым и неуправляемым миром выглядит немного неприятно (по сути, требуется приведение типов), но для вызывающего абонента в неуправляемом мире оно будет выглядеть и восприниматься нормально.
Удачи,