2009-09-24 4 views
5

J'ai un projet C# dll (my_cs_dll.dll) qui définit une classe statique avec une fonction membre statique. J'ai aussi un projet C++ dll qui utilise/clr.Comment appelez-vous une fonction gérée (C#) à partir de C++?

#using <my_cs_dll.dll> 

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

J'ai ajouté une référence à 'my_cs_dll.dll' dans le projet C++ Propriétés communes section Références (copie dépendances locales/copie sont vraies).

Et j'ai également ajouté le chemin d'accès à 'my_cs_dll.dll' dans la section Propriétés de configuration du projet C++ C/C++ Général 'Resolve # using References'.

Tout se construit sans erreur, mais à l'exécution, je reçois toujours une exception 'System.IO.FileNotFound' du système, affirmant qu'il ne trouve pas l'assembly my_cs_dll.dll.

Les deux Dll sont définitivement présentes dans le même répertoire que celui où je suis en train de tourner.

J'ai essayé toutes sortes de variations sur les paramètres mentionnés ci-dessus et lire tout ce que je pouvais trouver sur manged/Interop non géré, mais je ne peux pas sembler obtenir mon cerveau autour de ce qui est mal ...

I utilise VS2008 & .NET 3.5

Répondre

4

Il semble que votre assembly C# ne soit pas résolu au moment de l'exécution. Votre DLL C# est-elle dans le même répertoire que (ou un sous-répertoire de) votre exécutable? Cela fait un moment que je l'ai fait, mais je me souviens que si votre assembly est installé dans le GAC, il doit être dans le répertoire (ou un sous-répertoire) où se trouve votre exécutable, par opposition à l'emplacement de la DLL. il. Cela a à voir avec les fonctionnalités de sécurité .NET.

Si vous rencontrez toujours des problèmes, vous pouvez essayer d'utiliser vous-même la résolution de l'assemblage. Dans votre projet clr compatible C++, essayez d'ajouter les éléments suivants:

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

Vous pourriez avoir à modifier le code un peu pour le compiler dans votre projet. Dans mon cas, j'ai fait les deux fonctions méthodes statiques d'une classe dans mon projet clr-enabled. Assurez-vous d'appeler la fonction Resolve() dès le début de votre code, c'est-à-dire avant de tenter d'appeler le get_number_from_cs().

L'utilisation de COM est une option, mais elle n'est pas nécessaire. Vous êtes sur la bonne voie avec votre approche actuelle. Si vous voulez un peu de tenue de main, jetez un oeil à ce CodeProject example. C'est celui que je suis pour obtenir mon application non gérée pour utiliser mes assemblées managées.

+0

Salut Matt, « il doit être dans le répertoire (ou un sous-répertoire) où votre exécutable se trouve, par opposition à l'emplacement de la dll qui est de l'utiliser » Les dll sont imbriqués plusieurs sous-répertoires sous l'exe . Déplacer la DLL gérée dans le même répertoire que l'exécutable a permis de résoudre le problème. Merci! – mark

+0

OK, super. J'avais l'impression que tant que la DLL se trouvait dans un sous-répertoire de l'exécutable, quelle que soit sa profondeur, l'assemblage serait résolu. Mais comme je l'ai dit, ça fait un moment que j'ai regardé ça. –

+0

J'ai utilisé un code similaire lors du chargement de la DLL C# à partir d'une ressource incorporée. L'astuce était de placer ce code dans un fichier qui ne faisait pas référence à la DLL C#. Il semble que le retard-charge de.Les assemblys réseau se produisent lors de l'entrée dans une unité de compilation (un fichier .cpp) qui contient une référence à l'assembly en question, pas lorsque l'appel dans l'assembly référencé est réellement effectué, si jamais. – mheyman

Questions connexes