19

Is there a way to share an enum definition between native (unmanaged) C++ and (managed) C#?

I have the following enum used in completely unmanaged code:

enum MyEnum { myVal1, myVal2 };

Our application sometimes uses a managed component. That C# component gets the enum item values as ints via a managed C++ interop dll (from the native dll). (The interop dll only loads if the C# component is needed.) The C# component has duplicated the enum definition:

public enum MyEnum { myVal1, myVal2 };

Is there a way to eliminate the duplication without turning the native C++ dll into a managed dll?

sean e
  • 11,792
  • 3
  • 44
  • 56

5 Answers5

20

You can use a single .cs file and share it between both projects. #include in C++ on a .cs file should be no problem.

This would be an example .cs file:

#if !__LINE__    
namespace MyNamespace
{
    public 
#endif

// shared enum for both C, C++ and C#
enum MyEnum { myVal1, myVal2 };

#if !__LINE__
}
#endif

If you want multiple enums in one file, you can do this (although you have to temporarily define public to be nothing for 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
jjxtra
  • 20,415
  • 16
  • 100
  • 140
  • 1
    I just tested something similar - but the file is named MyEnum.cs. So that it compiles is C# without any special rules. In my C++ file this works: #include "MyEnum.cs" – sean e Jun 05 '09 at 19:35
  • Thanks for the help. Confirmed it works as expected - no change to C# project settings (other than adding link to the new cs file). Funny to see a #include of a .cs file in a C++. – sean e Jun 05 '09 at 22:53
  • Just use: #if __cpulsplus_cli – Yochai Timmer Jun 23 '13 at 18:07
  • @YochaiTimmer 1. there's a typo, should be: `__cplusplus_cli`; 2. in my opinion, `__cpulsplus_cli` cannot help distinguish unmanaged C++ (pure c++ without /clr) and C#, so it is not suitable for this question. – Tomingsun Aug 13 '21 at 03:57
  • 1
    Look at the edit history. It seems this answer has been edited quite a few times by random people. The original check i used, was #if WIN32 ... that is used in cli compiler and not c# – Yochai Timmer Aug 13 '21 at 06:59
5

Thanks for sharing!

I played around a bit and found a way to have multiple enum and constant declarations without having tons of extra lines :)

// 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

Remember to name your file *.cs

Johan Torp
  • 136
  • 2
  • 4
3

You can expose the C# library to COM and then import the type library into the unmanaged code - this way you will be able to use the enum defined in C# library in the unmanaged library.

sharptooth
  • 167,383
  • 100
  • 513
  • 979
  • That's an interesting approach. It has the side-effect that an otherwise unexposed enum becomes COM public. Unfortunately, the C# library may not run ever run/load due to framework incompatibility on target OSs. – sean e Jun 05 '09 at 16:28
  • @sean, you can selectively make specific enums public and others not using the ComVisibleAttribute. – Rami A. Jan 17 '12 at 19:49
0

Unmanaged C++ and C# live in two different worlds, so no there is no way to use the same enum, without changing the c++ DLL into a managed one.

And even then, you'd probably need the duplication in the managed C++ DLL.

A C++ enum is much like a list of constants, whereas a C# enum inherits the Enum class, and thus provides quite a few "tricks". So as you can see, they're very different.

If it doesn't matter whether the native C++ DLL is native or managed, I'd turn it into a managed one and wrap the native calls inside a managed C++ Layer.

That way you can have the enum duplication inside the C++ DLL, and also you can get rid of all the interop at the same time :-)

Steffen
  • 13,648
  • 7
  • 57
  • 67
0

I've had the same problem in the past and solved it using preprocessor definitions.

In your unmanaged code, inside a header that can also be included by your managed wrapper, place your enumeration items into a #define.

Then, in your managed and unmanaged enumeration definitions, use the same #define for both usages.

The movement of the enumerations between the managed and unmanaged world looks slightly nasty (basically a cast is needed), but to your caller in the unmanaged world, it'll look and feel fine.

Good luck,

Adrian Conlon
  • 3,941
  • 1
  • 21
  • 17