views:

1598

answers:

5

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?

A: 

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
Unfortunately, the native dll can not become managed.
sean e
+1  A: 

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
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
A: 

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,

Moleski
I'm missing something... use a header in C#?
sean e
A: 

I think it depends on exactly what you are trying to accomplish. Would generating one from the other be good enough for your problem?

Dolphin
Yes, generating one from the other during the build process would work.
sean e
What I want to accomplish is not having the enum duplicated. But I have runtime limitations - the C# library will only be installed in certain environments. The C# library is used to enhance functionality in the native dll only in a subset of the environments in which the native dll will run.
sean e
+3  A: 

Something in your build process would need to insert this enum into the C# file. If you don't have WIN32 defined as a pre-processor in your C++ project, you can use another pre-processor definition instead. This compiles in both C++ and C#:

#if !WIN32
    public
#endif
    enum MyEnum { myVal1, myVal2 };

UPDATE You can use a single .h file and share it between both projects, have the contents of the .h file be this:

#if !WIN32

namespace MyNamespace
{
    public
#endif

// shared enum for both C++ and C# - for C# make sure to set the build action of this file to 'Compile' as
// Visual Studio will think the .h is a regular content file by default.
enum MyEnum { myVal1, myVal2 };

#if !WIN32
}
#endif
John JJ Curtis
Alternately #if !__cplusplus public ...
sixlettervariables
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
Awesome, glad you got it working!
John JJ Curtis
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