2010-07-13 30 views
22

Tengo una biblioteca que consta de tres partes. Primero es C++ nativo, que proporciona la funcionalidad real. El segundo es un envoltorio/adaptador C++/CLI para la biblioteca C++, para simplificar la transición C# a C++. Finalmente tengo una biblioteca C#, que invoca la biblioteca C++ a través del adaptador C++/CLI.Compartiendo una enumeración de C#, C++/CLI y C++

En este momento no tengo dos conjuntos de definiciones de enumeración paralelos, uno almacenado en un archivo .cs y el otro en un archivo .h. Esto plantea un doble problema:

  1. Tengo doble mantenimiento. Siempre debo sincronizar los cambios de una enumeración en ambas ubicaciones de archivos.
  2. El espacio de nombre utilizado por ambas enumeraciones debe ser idéntico, pero el contenedor C++/CLI, que ve ambos conjuntos de enumeraciones y las traduce entre ellas, incurre en una colisión de nombres.

En este momento no estoy seguro de una solución como this o that resolvería ambos problemas. ¿Pensamientos?

+1

no es un duplicado, pero vea una pregunta similar: http: // stackoverflow.com/questions/954321/is-it-possible-to-share-an-enum-declaration-between-c-and-unmanaged-c –

+0

posible duplicado de [¿Cómo comparto una constante entre C# y código C++?] (http://stackoverflow.com/questions/3146017/how-do-i-share-a-constant-between-c-and-c-code) –

+0

@Billy: no es un duplicado, ya que la capa C++/CLI aquí da algunas opciones adicionales. No obstante, las respuestas en la publicación que proporcionó podrían ser útiles aquí también. –

Respuesta

2

sólo hay que poner su directiva #include "Enum.cs" dentro de un espacio de nombres externa para resolver la colisión de nombres.

EDITAR: Una variación sugerida por Brent es usar #define para sustituir uno de los espacios de nombres (o incluso el nombre de la enumeración en sí) declarado en el archivo .cs. Esto también evita la colisión de nombres, sin hacer que la jerarquía del espacio de nombres sea más profunda.

+0

¿Has leído mi comentario en Mystagogue en mi primera publicación? –

+0

Su método no permite usar el mismo archivo fuente directamente en C# y en proyectos nativos de C++. El mío no requiere macros. –

+0

Su método no permite el acceso a la enumeración administrada desde el proyecto C++/CLI, solo a la enumeración no gestionada. Por lo tanto, no se ajusta al requisito del OP. –

9

Incluso si incluye la enumeración de C# en su C++ nativo (como se sugiere en su first link), ambas enumeraciones no son "lo mismo", la enum de C++ no es más que una lista de enteros con nombre, mientras que C# enum de Enum. Como consecuencia, se produce una colisión en C++/CLI cuando se intenta usar ambos.

Una posible solución es usar el preprocesador para que su C++ montaje/CLI ve ambas enumeraciones en diferentes espacios de nombres:

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

En su código C++/CLI, hacer una inclusión como que:

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

Esto le proporciona la disponibilidad para distinguir entre esos dos tipos de enumeraciones EnumShare::MyEnum o EnumShareManaged::MyEnum en su código C++/CLI.

EDIT: acaba de encontrar this SO post que muestra la forma correcta de transmitir entre enums administrados y no administrados, seguramente esto también funcionará aquí. Por ejemplo, en el C++/CLI, la transición desde conseguido enumeración no administrado se puede hacer así:

void MyWrapperClass::MyWrapperFunction(EnumShareManaged::MyEnum mx) 
{ 
    EnumShare::MyEnum nx = static_cast<EnumShare::MyEnum>(mx); 
    // call a native function "func" 
    func(nx); 
} 
+0

¿Cómo ve el ensamblado C# el archivo "shared_enum.h"? Supongo que es más fácil tener C++ #include un "shared_enum.cs" que tener C# absorber de alguna manera un "shared_enum.h". ¿Sí? –

+1

@Mystagogue: si se incluye el shared_enum.h "administrado" en uno de sus archivos CPP (del proyecto de C++/CLI), la enumeración administrado se convierte en parte de la asamblea, y si hace referencia a este ensamblado desde C#, que es visible allí desde que fue declarado 'público'. Por otro lado, si declara la enumeración administrada en un "shared_enum.cs", no estará visible en su proyecto C++/CLI, ya que la C++/CLI no hace referencia a su proyecto C#, solo viceversa. –

+0

¡Ah! Si, pero maldita sea! Requisito adicional: Necesito admitir implementaciones x86 y x64. Mi código de cliente C# "AnyCPU" actualmente hace referencia a un ensamblaje C# de un intermediario que contiene interfaces y definiciones de enumeración. C++/CLI x86/x64, que también hace referencia al intermediario, se carga explícitamente en tiempo de ejecución por el cliente C#, en función de la arquitectura. En resumen, no puedo usar una técnica que dependa de una referencia de "tiempo de construcción" de C# en el conjunto C++/CLI. –

3

Considere programa generador de código, que lee el archivo h-archivo nativo con enumeraciones y genera otro h-archivo de la escritura , convirtiendo enum a la clase enum C++/CLI. Dicho generador de código se puede usar en el proyecto C++/CLI en el paso de compilación personalizada, produciendo las enumeraciones CLI requeridas.

que utilizan este enfoque para generar clases contenedoras nativos para conseguir Enum :: GetNames y funciones de enumeración :: GETNAME en C++ no administrado.

+0

También se utilizó este enfoque cuando se trata de aproximadamente 50 enumeraciones en un proyecto grande. La parte más importante fue establecer los enumeradores de enumeración administrados en los valores de enumerador no gestionados. –

+0

Incluso con un generador de código (que puede ser útil si tiene muchas enumeraciones) tiene que tratar de alguna manera con el problema de colisión de nombres. Mi sugerencia era "vivir con diferentes espacios de nombres y manejarlos correctamente". ¿Alguna mejor idea? –