2010-06-03 16 views
16

Soy desarrollador de Windows, estoy usando Microsoft visual studio 2008 SP1. Mi máquina de desarrollo es de 64 bits.AnyCPU/x86/x64 para la aplicación C# y su dependencia C++/CLI

El software en el que estoy trabajando actualmente es .exe administrado escrito en C#. Lamentablemente, no pude resolver todo el problema únicamente en C#. Es por eso que también desarrollé una pequeña DLL administrada en C++/CLI. Ambos proyectos están en la misma solución.

Mi objetivo de compilación de C# .exe es "Cualquier CPU". Cuando mi objetivo de compilación de C++ DLL es "x86", el archivo DLL no se carga. Por lo que entendí cuando busqué en Google, el motivo es el lenguaje C++/CLI, a diferencia de otros lenguajes .NET, se compila en el código nativo, no en el código administrado.

Cambié el objetivo de compilación de C++ DLL a x64, y todo funciona ahora. Sin embargo, AFAIK todo dejará de funcionar tan pronto como mi cliente instale mi producto en un sistema operativo de 32 bits. Tengo que admitir Windows Vista y 7, versiones de 32 y 64 bits de cada uno de ellos.

No quiero volver a los 32 bits. Las 250 líneas de código C++ en mi archivo DLL son solo el 2% de mi código base. Y esa DLL solo se usa en varios lugares, por lo que en el escenario de uso típico ni siquiera está cargada.

Mi DLL implementa dos objetos COM con ATL, por lo que no puedo usar la configuración de proyecto "/clr:safe".

¿Hay manera de configurar la solución y los proyectos de manera que C# proyecto se basa "Cualquier CPU" versión, el proyecto de C++ se basa ambas versiones 32 bits y 64 bits, a continuación, en el tiempo de ejecución cuando el .EXE administrado está empezando arriba, usa DLL de 32 bits o DLL de 64 bits dependiendo del sistema operativo?

¿O tal vez hay alguna solución mejor que no conozco?

¡Gracias de antemano!

+3

¿Hay una razón por la que no puedes simplemente distribuir dos versiones, una para x86 y otra para x64? –

+0

¿Estás seguro de que estás compilando C++ a CLI? – tgiphil

Respuesta

7

No hay una manera fácil de evitarlo. Si tiene código nativo (es decir, su C++) y necesita admitir x86, entonces tiene que compilar x86 (a menos que desee trabajar en el mundo WOW ... es decir, ejecutando código de 32 bits en entornos de 32 y 64 bits). Usted puede tener distribuciones x86 y x64, pero si admite 32 y 64 bits, y tiene código nativo o COM introp 'entonces tiene tiene binarios de 32 y 64 bits. "Cualquier CPU" solo es realmente útil cuando no hay código nativo o interoperabilidad, entonces obtienes ese beneficio.

+0

Sí, y el 98% de mi código está escrito en C#, y está administrado. Realmente me gustaría mantener solo 1 paquete de instalación y soporte la única versión de mi software. Creo que continuaré con "Cualquier CPU", e investigaré cómo cargar una de las 2 DLL dinámicamente, en el código C# .. ¡Gracias de todos modos! – Soonts

+0

@Soonts si usted crea correctamente su paquete de instalación, puede hacer que seleccione e instale los binarios correctos. Eso es lo que hago cuando colisionan las aplicaciones de servidor y los administradores idiotas :) – Gusdor

10

Hay una manera: tener un contenedor C# AnyCPU y un proyecto C++ por arquitectura, y dejar que el contenedor C# cargue el proyecto C++ correcto en tiempo de ejecución.

Para el proyecto C++, cree una versión por arquitectura diferente (x86, x64) y créelas todas. Luego, en la envoltura hacer:

public class CppWrapper 
{ 
    // C++ calls that will be dynamically loaded from proper architecture: 
    public static readonly Func<long> MyCplusplusMethodUsableFromCsharpSpace; 

    // Initialization: 
    static CppWrapper() 
    { 
     if(Environment.Is64BitProcess) 
     { 
      MyCplusplusMethodUsableFromCsharpSpace = CppReferences64.MyCplusplusClass.Method; 
      // Add your 64-bits entry points here... 
     } 
     else 
     { 
      MyCplusplusMethodUsableFromCsharpSpace = CppReferences32.MyCplusplusClass.Method; 
      /* Initialize new 32-bits references here... */ 
     } 
    } 

    // Following classes trigger dynamic loading of the referenced C++ code 
    private static class CppReferences64 
    { 
     public static readonly Func<long> MyCplusplusMethod = Cpp64.MyCplusplusMethod; 
     /* Add any64-bits references here... */ 
    } 
    private static class CppReferences32 
    { 
     public static readonly Func<long> MyCplusplusMethod = Cpp32.MyCplusplusMethod; 
     /* Add any 32-bits references here... */ 
    } 
} 

Y en el código C++, utilizo las mismas fuentes que he dicho, pero compilaré a diferentes espacio de nombres en función de la acumulación arquitectura:

#ifdef _M_X64 
namespace Cpp64 { 
#else 
namespace Cpp32 { 
#endif 
    public ref class MyCPlusPlusClass 
    { 
     public: static __int64 Method(void) { return 123; } 
    }; 
} 
+0

Su clase C# no puede compilar, ya que la DLL administrada por C++ solo contendrá Cpp64 o Cpp32, pero no ambos. – imekon

Cuestiones relacionadas