Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sharing an enum from C#, C++/CLI, and C++

Tags:

I have a library that consists of three parts. First is native C++, which provides the actual functionality. Second is a C++/CLI wrapper/adaptor for the C++ library, to simplify the C# to C++ transition. Finally I have a C# library, which invokes the C++ library through the C++/CLI adaptor.

Right now there I have two sets of parallel enum definitions, one stored in a .cs file and the other in a .h file. This poses a double problem:

  1. I have dual maintenance. I must always synchronize changes of an enum in both file locations.
  2. The namespace used by both enums should be identical but the C++/CLI wrapper, which views both sets of enums and translates between them, incurs a naming collision.

Right now I'm not sure a solution such as this or that would solve both problems. Thoughts?

like image 353
Brent Arias Avatar asked Jul 13 '10 18:07

Brent Arias


2 Answers

Even if you include the C# enum in your native C++ (as suggested in your first link), both enums are not "the same", the C++ enum is nothing but a list of named integers, while the C# enum is derived from Enum. As a consequence, you get a collision in C++/CLI when trying to use them both.

A possible solution is to use the preprocessor so that your C++/CLI assembly sees both enums in different namespaces:

// 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,     }; } 

In your C++/CLI code, make an inclusion like that:

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

This gives you the availability to distinguish between those two kind of enums EnumShare::MyEnum or EnumShareManaged::MyEnum in your C++/CLI code.

EDIT: just found this SO post showing the correct way to cast between unmanaged and managed enums, this surely will work here, too. For example, in the C++/CLI, the transition from managed to unmanaged enum can be done like this:

void MyWrapperClass::MyWrapperFunction(EnumShareManaged::MyEnum mx) {     EnumShare::MyEnum nx = static_cast<EnumShare::MyEnum>(mx);     // call a native function "func"     func(nx); } 
like image 102
Doc Brown Avatar answered Oct 05 '22 00:10

Doc Brown


Consider writing code generator program, which reads native h-file file with enumerations and generates another h-file, converting enum to C++/CLI enum class. Such code generator can be used in C++/CLI project on the Custom Build Step, producing required CLI enumerations.

I use this approach to generate native wrapper classes to get Enum::GetNames and Enum::GetName functions in unmanaged C++.

like image 30
Alex F Avatar answered Oct 04 '22 23:10

Alex F