2009-09-24 18 views
5

Tengo un proyecto C# dll (my_cs_dll.dll) que define una clase estática con una función miembro estática.¿cómo se llama una función administrada (C#) desde C++?

namespace Foo 
{ 
    public static class Bar 
    { 
     public static double GetNumber() { return 1.0; } 
    } 
} 

I también tienen un proyecto DLL C++ que está utilizando/clr.

#using <my_cs_dll.dll> 

double get_number_from_cs() { return Foo::Bar::GetNumber(); } 

He añadido una referencia a 'my_cs_dll.dll' en el proyecto de C++ Propiedades comunes hace referencia a la sección (copiar dependencias locales/copia son verdaderas).

Y también he agregado la ruta de acceso a 'my_cs_dll.dll' en la sección C++ 'Propiedades de configuración C/C++ Proyecto general' Resolución 'usando referencias'.

Todo se genera sin error, sin embargo, en tiempo de ejecución sigo obteniendo una excepción 'System.IO.FileNotFound' del sistema que alega que no puede encontrar el ensamblaje my_cs_dll.dll.

Ambos Dll están definitivamente presentes en el mismo directorio desde el que estoy ejecutando.

que han intentado todo tipo de variaciones sobre los ajustes mencionados anteriormente y leer todo lo que pude encontrar en manejadas interoperabilidad/no administrado, pero me parece que no puede conseguir mi cerebro alrededor de lo que está mal ...

I Estoy usando VS2008 & .NET 3.5

Respuesta

4

Parece que su ensamblado C# no se resuelve en el tiempo de ejecución. ¿Su dll C# está en el mismo directorio que (o un subdirectorio de) su ejecutable? Ha pasado un tiempo desde que hice esto, pero mi recuerdo es que a menos que su ensamblado esté instalado en el GAC, debe estar en el directorio (o en un subdirectorio) donde se encuentra el ejecutable, a diferencia de la ubicación del dll que está utilizando eso. Esto tiene que ver con las características de seguridad de .NET.

Si aún tiene problemas, puede intentar resolver el ensamblaje usted mismo. En su proyecto CLR habilitado para C++, trate de añadir lo siguiente:

using namespace System; 
using namespace System.Reflection; 
void Resolve() 
{ 
    AppDomain::CurrentDomain->AssemblyResolve += 
     gcnew ResolveEventHandler(OnAssemblyResolve); 
} 
Assembly ^OnAssemblyResolve(Object ^obj, ResolveEventArgs ^args) 
{ 
#ifdef _DEBUG 
    String ^path = gcnew String(_T("<path to your debug directory>")); 
#else 
    String ^path = gcnew String(_T("<path to your release directory>")); 
#endif 
    array<String^>^ assemblies = 
     System::IO::Directory::GetFiles(path, _T("*.dll")); 
    for (long ii = 0; ii < assemblies->Length; ii++) { 
     AssemblyName ^name = AssemblyName::GetAssemblyName(assemblies[ii]); 
     if (AssemblyName::ReferenceMatchesDefinition(gcnew AssemblyName(args->Name), name)) { 
      return Assembly::Load(name); 
     } 
    } 
    return nullptr; 
} 

Es posible que tenga que modificar el código un poco para que se compile en su proyecto. En mi caso, hice las dos funciones de métodos estáticos de una clase en mi proyecto habilitado para clr. Simplemente asegúrese de llamar a la función Resolve() desde el principio en su código, es decir, antes de intentar llamar al get_number_from_cs().

Si bien usar COM es una opción, no es necesario. Estás en el camino correcto con tu enfoque actual. Si desea algo de mano, eche un vistazo a este CodeProject example. Es el que sigo para que mi aplicación no administrada use mis ensamblajes administrados.

+0

Hola Matt, "que debe estar en el directorio (o un subdirectorio) donde se encuentra el ejecutable, en oposición a la ubicación de la DLL que lo está usando" Los DLL se anidan varios subdirectorios debajo del exe . Al mover el dll administrado al mismo directorio que el ejecutable, se solucionó el problema. ¡Gracias! – mark

+0

OK, genial. Tenía la impresión de que, siempre que el dll estuviese en un subdirectorio del ejecutable, independientemente de la profundidad, el ensamblaje se resolvería. Pero como dije, ha pasado un tiempo desde que miré esto. –

+0

Utilicé un código similar al cargar la DLL C# de un recurso incrustado. El truco fue colocar este código en un archivo que no hacía referencia a la DLL de C#. Parece que la carga de retraso de.Los ensamblajes de red se producen al ingresar a una unidad de compilación (un archivo .cpp) que contiene una referencia al ensamblado en cuestión, no cuando la llamada al ensamblado al que se hace referencia se realiza, si es que lo hace alguna vez. – mheyman

Cuestiones relacionadas