2009-09-24 17 views
5

Ho un progetto C# dll (my_cs_dll.dll) che definisce una classe statica con una funzione membro statica.come si chiama una funzione gestita (C#) da C++?

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

Ho anche un progetto C++ dll che utilizza/clr.

#using <my_cs_dll.dll> 

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

ho aggiunto un riferimento alla 'my_cs_dll.dll' nel C++ progetto Proprietà comuni sezione Riferimenti (Copia/dipendenze copia locale sono entrambi True).

E ho anche aggiunto il percorso a 'my_cs_dll.dll' nel progetto C++ Proprietà di configurazione C/C++ Generale "Risolvi # utilizzando la sezione Riferimenti".

Tutto si genera senza errori, tuttavia in fase di esecuzione continuo a ricevere un'eccezione 'System.IO.FileNotFound' dal sistema che afferma che non è possibile trovare l'assembly my_cs_dll.dll.

Entrambe le Dll sono sicuramente presenti nella stessa directory da cui sono in esecuzione.

Ho provato tutti i tipi di variazioni sulle impostazioni di cui sopra e leggere tutto ciò che ho potuto trovare su manged interoperabilità/non gestito, ma io non riesco a ottenere il mio cervello intorno a ciò che è sbagliato ...

I Sto usando VS2008 & .NET 3.5

risposta

4

Sembra che il tuo assembly C# non venga risolto in fase di runtime. La tua C# dll è nella stessa directory di (o una sottodirectory di) il tuo eseguibile? È passato un po 'di tempo da quando l'ho fatto, ma il mio ricordo è che, a meno che l'assembly non sia installato nel GAC, deve trovarsi nella directory (o in una sottodirectory) in cui si trova il tuo eseguibile, al contrario della posizione della dll che sta usando esso. Questo ha a che fare con le funzionalità di sicurezza .NET.

Se si riscontrano ancora problemi, provare a utilizzare l'assieme per risolvere il problema. Nel progetto CLR abilitati C++, prova ad aggiungere il seguente:

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

potrebbe essere necessario modificare il codice un po 'per farlo compilare nel progetto. Nel mio caso, ho reso le due funzioni metodi statici di una classe nel mio progetto abilitato clr. Assicurati di chiamare la funzione Resolve() nella parte iniziale del tuo codice, ad es., Prima di provare a chiamare get_number_from_cs().

Mentre usare COM è un'opzione, non è necessaria. Sei sulla strada giusta con il tuo approccio attuale. Se vuoi un po 'di mano, dai un'occhiata a questo CodeProject example. È quello che sto seguendo per far sì che la mia applicazione non gestita utilizzi i miei assembly gestiti.

+0

Ciao Matt, "deve essere nella directory (o in una sottodirectory) in cui si trova l'eseguibile, in contrasto con la posizione del dll che sta usando" la DLL di sono annidate diverse sotto-directory sotto l'exe . Lo spostamento della DLL gestita nella stessa directory dell'eseguibile ha risolto il problema. Grazie !! – mark

+0

OK, fantastico. Avevo l'impressione che finché la DLL si trovava in una sottodirectory dell'eseguibile, indipendentemente da quanto fosse profonda, l'assemblea sarebbe stata risolta. Ma come ho detto, è passato un po 'di tempo da quando ho guardato questo. –

+0

Ho usato un codice simile durante il caricamento della DLL C# da una risorsa incorporata. Il trucco consisteva nel posizionare questo codice in un file che non faceva riferimento alla DLL C#. Sembra che il ritardo di caricamento di.Gli assembly netti si verificano quando si accede a un'unità di compilazione (un file .cpp) che contiene un riferimento all'assembly in questione, non quando la chiamata nell'assembly referenziato viene effettivamente realizzata, se mai. – mheyman

Problemi correlati