469,271 Members | 1,743 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,271 developers. It's quick & easy.

C++/CLI managed Enum appears empty in CSharp


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/lib...49(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.
Nov 22 '06 #1
12 6222
Use public enum class instead of public enum.

Marcus

"Cmtk Software" <Cm**********@newsgroup.nospamwrote in message
news:1A**********************************@microsof t.com...
>
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/lib...49(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.

Nov 22 '06 #2
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/lib...49(VS.80).aspx

--
Kind regards,
Bruno.
br**********************@hotmail.com
Remove only "_nos_pam"

Nov 22 '06 #3
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.
"Bruno van Dooren [MVP VC++]" wrote:
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/lib...49(VS.80).aspx

--
Kind regards,
Bruno.
br**********************@hotmail.com
Remove only "_nos_pam"
Nov 22 '06 #4
>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/lib...49(VS.80).aspx

--
Kind regards,
Bruno.
br**********************@hotmail.com
Remove only "_nos_pam"
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.

Nov 22 '06 #5
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!

"Marcus Heege" wrote:
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/lib...49(VS.80).aspx

--
Kind regards,
Bruno.
br**********************@hotmail.com
Remove only "_nos_pam"

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.

Nov 22 '06 #6
I guess I have to agree that there is no good solution to this problem ...

Marcus

"Cmtk Software" <Cm**********@newsgroup.nospamwrote in message
news:B9**********************************@microsof t.com...
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!

"Marcus Heege" wrote:
>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/lib...49(VS.80).aspx

--
Kind regards,
Bruno.
br**********************@hotmail.com
Remove only "_nos_pam"

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.


Nov 23 '06 #7
"Marcus Heege" <no****@heege.netwrote in message
news:eo**************@TK2MSFTNGP04.phx.gbl...
>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.

Nov 24 '06 #8

"Marcus Heege" <no****@heege.netwrote in message
news:eo**************@TK2MSFTNGP04.phx.gbl...
>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

"Cmtk Software" <Cm**********@newsgroup.nospamwrote in message
news:B9**********************************@microsof t.com...
>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!

"Marcus Heege" wrote:
>>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/lib...49(VS.80).aspx

--
Kind regards,
Bruno.
br**********************@hotmail.com
Remove only "_nos_pam"

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.



Nov 24 '06 #9
"Ben Voigt" <rb*@nospam.nospamwrote in message
news:um*************@TK2MSFTNGP03.phx.gbl...
>
"Marcus Heege" <no****@heege.netwrote in message
news:eo**************@TK2MSFTNGP04.phx.gbl...
>>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
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
Nov 24 '06 #10

"Marcus Heege" <no****@heege.netwrote in message
news:eK*************@TK2MSFTNGP06.phx.gbl...
"Ben Voigt" <rb*@nospam.nospamwrote in message
news:um*************@TK2MSFTNGP03.phx.gbl...
>>
"Marcus Heege" <no****@heege.netwrote in message
news:eo**************@TK2MSFTNGP04.phx.gbl...
>>>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

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

Dec 5 '06 #11
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.

"Ben Voigt" wrote:
>
"Marcus Heege" <no****@heege.netwrote in message
news:eK*************@TK2MSFTNGP06.phx.gbl...
"Ben Voigt" <rb*@nospam.nospamwrote in message
news:um*************@TK2MSFTNGP03.phx.gbl...
>
"Marcus Heege" <no****@heege.netwrote in message
news:eo**************@TK2MSFTNGP04.phx.gbl...
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
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.

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


Feb 11 '07 #12

"Cmtk Software" <Cm**********@newsgroup.nospamwrote in message
news:BE**********************************@microsof t.com...
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.
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
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.

"Ben Voigt" wrote:
>>
"Marcus Heege" <no****@heege.netwrote in message
news:eK*************@TK2MSFTNGP06.phx.gbl...
"Ben Voigt" <rb*@nospam.nospamwrote in message
news:um*************@TK2MSFTNGP03.phx.gbl...

"Marcus Heege" <no****@heege.netwrote in message
news:eo**************@TK2MSFTNGP04.phx.gbl...
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

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.

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



Feb 12 '07 #13

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

13 posts views Thread by Martin | last post: by
21 posts views Thread by Andreas Huber | last post: by
1 post views Thread by Bae,Hyun-jik | last post: by
reply views Thread by Ewart MacLucas | last post: by
3 posts views Thread by Cmtk Software | last post: by
3 posts views Thread by =?Utf-8?B?Sm9hY2hpbQ==?= | last post: by
3 posts views Thread by Dean Mitchell | last post: by
2 posts views Thread by puzzlecracker | last post: by
1 post views Thread by CARIGAR | last post: by
reply views Thread by zhoujie | last post: by
reply views Thread by suresh191 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.