2009-09-24 24 views
5

Mam projekt C# dll (my_cs_dll.dll), który definiuje klasę statyczną z funkcją statycznego elementu.jak wywołać funkcję managed (C#) z C++?

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

Mam również projekt dll C++, który używa/clr.

#using <my_cs_dll.dll> 

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

Dodałem odniesienie do 'my_cs_dll.dll' w C++ projektu wspólnych właściwości odwołuje sekcję (kopia lokalna kopia/Zależności są zarówno prawdziwe).

Dodałem również ścieżkę do 'my_cs_dll.dll' w projekcie C++ Właściwości konfiguracji C/C++ Ogólne "Rozwiąż # używając odnośników".

Wszystko buduje się bezbłędnie, jednak w czasie wykonywania otrzymuję wyjątek "System.IO.FileNotFound" z systemu, który twierdzi, że nie może znaleźć zespołu my_cs_dll.dll.

Obie biblioteki DLL są zdecydowanie obecne w tym samym katalogu, z którego korzystam.

Próbowałem wszystkie rodzaje wariacji na temat ustawień wymienionych powyżej i czytać wszystko udało mi się znaleźć na manged/niekontrolowana współdziałanie, ale nie wydaje się dostać mój mózg wokół tego, co jest nie tak ...

I 'm przy użyciu VS2008 & .NET 3.5

Odpowiedz

4

Wygląda na to, że Twój zestaw C# nie jest rozwiązywany w czasie wykonywania. Czy twój plik DLL C# znajduje się w tym samym katalogu co (lub podkatalog) twojego pliku wykonywalnego? Minęło trochę czasu, odkąd to zrobiłem, ale moim wspomnieniem jest to, że jeśli twój zespół nie jest zainstalowany w GAC, musi znajdować się w katalogu (lub podkatalogu), w którym znajduje się twój plik wykonywalny, w przeciwieństwie do lokalizacji biblioteki DLL, która używa to. Ma to związek z funkcjami zabezpieczeń .NET.

Jeśli nadal występują problemy, możesz spróbować samodzielnie rozwiązać proces montażu. W swoim projekcie C++ CLR włączona, spróbuj dodać następujące:

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

Być może trzeba będzie dostosować kod trochę zmusić go do kompilacji w projekcie. W moim przypadku utworzyłem dwie funkcje statycznych metod klasy w moim projekcie z obsługą clr. Po prostu upewnij się, że wcześnie wywołujesz funkcję Resolve() w swoim kodzie, tj. Zanim spróbujesz zadzwonić pod numer get_number_from_cs().

Podczas korzystania z COM jest opcja, nie jest konieczne. Jesteś na właściwej ścieżce z obecnym podejściem. Jeśli chcesz trochę trzymania ręki, spójrz na to CodeProject example. To jest ten, który śledzę, aby uzyskać moją niezarządzaną aplikację do korzystania z zarządzanych przeze mnie zespołów.

+0

Cześć Matt, „musi znajdować się w katalogu (lub podkatalogu), gdzie plik wykonywalny znajduje się, w przeciwieństwie do lokalizacji dll to jest to za pomocą” W DLL są zagnieżdżone kilka podkatalogów pod exe . Przeniesienie zarządzanej biblioteki dll do tego samego katalogu, co plik wykonywalny, spowodowało usunięcie problemu. Dziękujemy! – mark

+0

OK, świetnie. Miałem wrażenie, że tak długo, jak dll znajduje się w podkatalogu pliku wykonywalnego, niezależnie od tego, jak głęboko, zespół zostanie rozwiązany. Ale jak już powiedziałem, minęło trochę czasu, odkąd na to patrzyłem. –

+0

Użyłem podobny kod podczas ładowania biblioteki DLL C# z osadzonego zasobu. Sztuczka polegała na umieszczeniu tego kodu w pliku, który nie odwoływał się do biblioteki DLL C#. Wydaje się, że opóźnienie-obciążenia.Zespoły sieciowe występują po wejściu do jednostki kompilacji (pliku .cpp), która zawiera odniesienie do danego zespołu, a nie kiedy wywołanie w zestawie referencyjnym jest faktycznie wykonane, jeśli w ogóle. – mheyman

Powiązane problemy