Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / Languages / Managed C++ / February 2007

Tip: Looking for answers? Try searching our database.

C++/CLI managed Enum appears empty in CSharp

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Cmtk Software - 22 Nov 2006 07:38 GMT
I'm trying to define an enum which will be used from unmanaged c++, C++/CLI
managed c++ and from C#.
I defined the following enum in a VS dll project set to be compiled with the
/clr switch:

public enum Days
{
   Sunday
};

After building the project, I added the created DLL as a reference in a C#
project.
Trying to use this enum from inside the C# project, Days itself was visible
but none of its fields (Sunday) existed (Days was empty).
For verification, I right clicked on the DLL reference and selected "View in
Object Browser". Again, "Days" existed but was empty - Sunday simply wasn't
there.
I tried creating an enum class in the CLI managed c++ project:
public enum class Days
{
   Sunday
};

And both the enum itself and its fields were visible and usable from C#.
However this cannot be my solution because the "enum class" cannot be used
from unmanaged c++.

The enum class reference on MSDN
(http://msdn2.microsoft.com/en-us/library/a6cskb49(VS.80).aspx) states:
"A named, standard enum compiled with /clr will be visible in the assembly
as a managed enum, and can be consumed by any other managed compiler."

How can I make Sunday accessible from C#?

Thanks in advance.
Marcus Heege - 22 Nov 2006 10:26 GMT
Use public enum class instead of public enum.

Marcus

> I'm trying to define an enum which will be used from unmanaged c++,
> C++/CLI
[quoted text clipped - 36 lines]
>
> Thanks in advance.
Bruno van Dooren [MVP VC++] - 22 Nov 2006 10:54 GMT
> Use public enum class instead of public enum.

Hi Marcus,

He wanted to use an unmanaged enum because that way it could be used both in
managed and unmanaged code.
According to MSDN an unmanaged enum compiled with /clr should be inserted
into the assembly as a managed enum.
see
http://msdn2.microsoft.com/en-us/library/a6cskb49(VS.80).aspx

Signature

Kind regards,
   Bruno.
   bruno_nos_pam_van_dooren@hotmail.com
   Remove only "_nos_pam"

Cmtk Software - 22 Nov 2006 11:10 GMT
Hi Bruno,

I read the MSDN page you mentioned (I also referenced it in my post). The
problem is, as I mentioned in my question, that from inside C#, the enum
seems empty.
This code in CLI:

public enum Days
{
    Sunday
};

Producing the following metadata:

public enum Days
{
}

- An empty enum. I know this contradicts what is written in the MSDN page
you mentioned.
Can you please explain why this happens.

> > Use public enum class instead of public enum.
>
[quoted text clipped - 6 lines]
> see
> http://msdn2.microsoft.com/en-us/library/a6cskb49(VS.80).aspx
Marcus Heege - 22 Nov 2006 14:11 GMT
>> Hi Marcus,
>>
[quoted text clipped - 5 lines]
>> see
>> http://msdn2.microsoft.com/en-us/library/a6cskb49(VS.80).aspx

OOps It seems I read that question too quick.

Here is some background info:

For native types like structs, classes, enums, and unions, the C++/CLI
compiler generates managed wrapper types as soon as these are used in
managed code. However, these wrapper types are more primitive as one might
think. For structs, classes, and unions, they are value types without any
fields. Only the native size of the struct, class, or union is specified in
the metadata. For enums, a managed enum is created, however, it only
contains the standard field to store the value.

Here is the solution that I would suggest:

To see the enum values on both sides, you should define two enums:

In your assembly a public managed enum:
public enum class E
{ a, b, c };

In the header that is included in C++ projects, an equivalent native enum:
#ifndef _MANAGED
enum E
{ a, b, c };
#else
#using "yourAssembly.dll"
#endif

If the header is included in a file compiled with /clr:* or, the managed
enum will be visible, because
   #using "yourAssembly.dll"
will be compiled with your code.
If the header is included in a file complied without /clr:*, the native enum
will be defined.
Cmtk Software - 22 Nov 2006 16:14 GMT
Hi Marcus,

Thanks alot for all the background information!
Your solution creates a double definition of the enum (This enum is defined
in two different places) and so, might create a problem in the future when
someone changes one enum and doesn't know he should also change the other one
accordingly.
This's why I wanted all factors to use the same enum definition.

The solution I used temporarly is:
enum Days
{
   Day_Sunday,
   Day_Monday
};

public enum class ManagedDays
{
   Sunday = Day_Sunday,
   Monday = Day_Monday,
};

This way values of the items in both enums corresponds.
I'll keep looking for a way to define only one enum which will be usable by
all. If I do find such a way, I'll post it in this thread.

Again, thanks for your help!

> >> Hi Marcus,
> >>
[quoted text clipped - 40 lines]
> If the header is included in a file complied without /clr:*, the native enum
> will be defined.
Marcus Heege - 23 Nov 2006 10:12 GMT
I guess I have to agree that there is no good solution to this problem ...

Marcus

> Hi Marcus,
>
[quoted text clipped - 77 lines]
>> enum
>> will be defined.
Marcus Heege - 24 Nov 2006 10:05 GMT
>I guess I have to agree that there is no good solution to this problem ...
>
> Marcus

One last attempt. How about this:

[assembly: ComVisible(false)]  // ensure that all other types do not end up
in the COM type library

[ComVisible(true)]                    // ensure that the enum type ends up
in the COM type library
public enum class Days
{
 Monday, // ...
};

Managed clients can use this by just referencing the assembly. Native
clients can use this enum via #import.
Ben Voigt - 24 Nov 2006 15:21 GMT
>I guess I have to agree that there is no good solution to this problem ...

#include the same header file twice, with different #defines:

#define ENUMDECL enum class
#include "enumdef.h"
#undef ENUMDECL

#define ENUMDECL enum
#include "enumdef.h"
#undef ENUMDECL

> Marcus
>
[quoted text clipped - 81 lines]
>>> enum
>>> will be defined.
Marcus Heege - 24 Nov 2006 18:06 GMT
>>I guess I have to agree that there is no good solution to this problem ...
>
[quoted text clipped - 7 lines]
> #include "enumdef.h"
> #undef ENUMDECL

The problem with this approach is that it break the rules of managed type
identity. Including this header in two different projects would produce two
different managed enums.

Marcus
Ben Voigt - 05 Dec 2006 22:02 GMT
>>>I guess I have to agree that there is no good solution to this problem
>>>...
[quoted text clipped - 12 lines]
> identity. Including this header in two different projects would produce
> two different managed enums.

The header file is for the library and native clients (with appropriate
preprocessor conditionals to remove the C++/CLI definitions when used from
standard C++), while managed clients don't use #include at all but #import.

> Marcus
Cmtk Software - 11 Feb 2007 08:35 GMT
Dear Ben,

My solution includes a managed project (compiled with /clr), which is linked
to a DLL.
I have two classes in this DLL: a native worker and its managed (ref) wrapper.
This's why I need an enum which can be used by C# (which references this
library), managed c++ and native c++.
I already tried your solution (to include the header with the enum
definition twice). It causes a linkage error because both the native enum and
the managed enum are exported and visible for the DLL clients and therefore
cannot have the same name.
The problem is that the native enum is exported empty and its fields are not
exported.

I'm still battling this one and the temporary solution I mentioned a few
posts back is becoming more and more permanent...

Any suggestion will be appreciated.

> >>>I guess I have to agree that there is no good solution to this problem
> >>>...
[quoted text clipped - 18 lines]
>
> > Marcus
Ben Voigt - 12 Feb 2007 20:59 GMT
> Dear Ben,
>
[quoted text clipped - 11 lines]
> therefore
> cannot have the same name.
Can you just give them different names, via a second #define?

Or else put them inside different namespaces?

namespace dotnet {
#define ENUMDECL enum class
#include "enumdef.h"
#undef ENUMDECL
}
namespace native {
#define ENUMDECL enum
#include "enumdef.h"
#undef ENUMDECL
}

> The problem is that the native enum is exported empty and its fields are
> not
[quoted text clipped - 30 lines]
>>
>> > Marcus

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.