Pregunta

Estoy escribiendo dos procesos usando C # y WCF para uno y C ++ y WWSAPI para el segundo. Quiero ser capaz de definir la dirección que se utiliza para la comunicación entre los dos en un solo lugar y tienen tanto C # y C ++ usarlo. ¿Es esto posible?

Lo más cerca que he llegado es la definición de la constante en un IDL, a continuación, utilizando de MIDL y TLBIMP conseguirlo en un archivo DLL que puede ser consumido por C #. Sin embargo, esto no parece para exponer la constante, o al menos yo no puede encontrar la manera de hacer que funcione. Tal vez se limita a las definiciones de tipo solamente.

¿Alguna otra sugerencia?

¿Fue útil?

Solución

C # y C ++ tienen diferentes modelos para las constantes. Típicamente, la constante incluso no ser emitida en el C ++ binario resultante -. Es reemplazado automáticamente donde se necesita la mayoría del tiempo

En lugar de usar la constante de, hacer una función que devuelve la constante, que se puede P / Invoke desde C #.

Por lo tanto,

#include <iostream>
const double ACCELERATION_DUE_TO_GRAVITY = 9.8;
int main()
{
     std::cout << "Acceleration due to gravity is: " << 
         ACCELERATION_DUE_TO_GRAVITY;
}

se convierte

#include <iostream>
extern "C" double AccelerationDueToGravity()
{
    return 9.8;
}
int main()
{
     std::cout << "Acceleration due to gravity is: " << 
         AccelerationDueToGravity();
}

que debe ser capaz de P / Invoke desde C #.

Otros consejos

Puede crear un proyecto de C ++ / CLI separada y definir todas las constantes en un archivo .h. Por ejemplo, crear proyecto de C ++ / CLI biblioteca de clases llamado "ConstantBridge" y un proyecto de C # llamado "CSharpProgram":

constants.h

namespace Constants
{
    const int MAGIC_NUMBER = 42;
}

// String literals must be defined as macros
#define MAGIC_PHRASE "Hello World"

// Since stirngs must be macros it's arguably more consistent 
// to use `define` throughout. This is for demonstration purpose.

ConstantBridge.h

#include "Constants.h"

namespace ConstantBridge { public ref class ConstantBridge {
public:
    // The use of the `literal` keyword is important
    // `static const` will not work
    literal int kMagicNumber = Constants::MAGIC_NUMBER;
    literal String ^ kMagicPhrase = MAGIC_PHRASE;
};}

CSharpProgram.cs

Console.WriteLine(ConstantBridge.kMagicNumber); // "42"
Console.WriteLine(ConstantBridge.kMagicPhrase); // "Hello World"

Ahora, tienen la "CSharpProgram" referencia del proyecto del proyecto "ConstantBridge". Sus otros proyectos nativo de C ++ puede simplemente #include "Constants.h".

Mientras se hace referencia a solamente literals del proyecto ConstantBridge, no se generará una dependencia de tiempo de ejecución. Puede comprobar el uso de ILSpy o ILDASM. const en C # y literal en C ++ / CLI son copiado "literalmente" en la página de llamada durante la compilación.

no estaba contento con las otras soluciones para mi caso de uso de modo codificado a una solución ligeramente hacky que parece encajar mejor la solicitud original; una constante en un archivo que puede ser integrado en ambos a C # y un proyecto de C ++ ...

  1. Información de la versión de un archivo .cs, en un lugar común.

De esta manera:

// Version.cs
public static class MyAppVersion
{
    //build
    public static string Number = "1.0";
    public static string Phase = "Alpha";

    //configuration (these are the build constants I use, substitute your own)
#if BUILD_SHIPPING
    public static string Configuration = "Shipping";
#elif BUILD_DEVELOPMENT
    public static string Configuration = "Development";
#elif BUILD_DEBUG
    public static string Configuration = "Debug";
#else
    "build type not defined"
#endif
}
  1. Incluir en el proyecto de C # utilizando Agregar elemento existente ... [Agregar Como Link]
  2. Incluir en el proyecto de C ++ (en un archivo .cpp) con un #include

De esta manera:

//include version information into a .cpp
#define class namespace
#define public
#define static
#define string const char*
#include "..\..\Version.cs" //or to where-ever your file is
;
#undef class
#undef public
#undef static
#undef string
  1. Referencia en C # con: MyAppVersion.Number
  2. Referencia en C ++ con: MyAppVersion::Number

Cuando he tenido que hacer eso en el pasado, simplemente he añadido una etapa de pre-compilación extra para el proceso de construcción, que automagicamente crea un archivo de otro.

Desde sus constantes probablemente será dentro de una clase en C #, se puede usar eso como el archivo de origen:

MyClass.cs:
    class MyClass {
        public const int NUM_MONTHS = 12;    //COMMON
        public const int YEAR_BASE = 1900;   //COMMON
    }

grep '//COMMON' MyClass.cs
    | sed -e 's/^ *public const [a-z][a-z]*/#define/'
          -e 's/ *= */ /'
          -e 's/;.*$//'
    >MyClass.h
grep '//COMMON' MyClass.cs | sed -e 's/ *public //' -e 's/;.*$/;/' >MyClass.hpp

Esto le dará:

MyClass.h:
    #define NUM_MONTHS 12
    #define YEAR_BASE 1900

MyClass.hpp:
    const int NUM_MONTHS = 12;
    const int YEAR_BASE = 1900;

Ahora, conseguir Visual Studio para llevar a cabo ese paso no es algo que sé hacer. Vas a tener que investigar si es o no es aún posible. Las herramientas de procesamiento de texto UNIXy son realmente vale la pena descargar. Tengo CygWin instalado en unas cuantas cajas, pero, por algo esta localizada, que podría salirse con la persona paquetes GnuWin32 .

Probablemente se podría hacer un trabajo similar en PowerShell, pero no estoy muy versado en eso.


Ahora que es un poco de un kludge por lo que puede sugerir una posiblemente mejor manera para que usted pregunta en particular. No uso una constante en absoluto. Poner la dirección en un archivo de configuración y tener su código C # y C ++ leyó en el inicio.

De esta manera, se llega a compartir el valor sin dolor y Es configurable en caso de que desee cambiar en el futuro.

Una alternativa más fácil a un método para cada constante puede ser una clase contiene las constantes como propiedades de la instancia. Se puede crear en C # y exponerla a través de interfaces COM para C ++. Eso es más fácil y menos propenso a errores que P / Invoke, ya que no tiene que preocuparse de conseguir todos los tipos y nombres de la derecha -. Todo está hecho para usted por el compilador

Nota:. No he probado esto, sólo estoy especulando que debe de trabajo

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top