2008-08-22 15 views
16

Mam problem podobny do, ale subtelnie różny od opisanego here (ładowanie złożeń i ich zależności).Jak późno związać biblioteki 32-bitowe/64-bitowe w środowisku wykonawczym

Mam DLL C++ dla renderowania 3D, który jest tym, co sprzedajemy klientom. Dla użytkowników .NET będziemy mieli wokół niego opakowanie CLR. DLL C++ może być zbudowany zarówno w wersjach 32, jak i 64-bitowych, ale myślę, że oznacza to, że potrzebujemy dwóch wrapperów CLR, ponieważ CLR wiąże się z określoną biblioteką DLL?

Powiedzmy, że nasz klient ma aplikację .NET, która może być 32 lub 64-bitowa, i że jest to czysta aplikacja .NET, porzuca CLR, aby wykonać ją z jednego zestawu złożeń. Pytanie brzmi, w jaki sposób kod aplikacji może dynamicznie wybierać między 32 a 64-bitowymi kombinacjami CLR/DLL w czasie wykonywania?

Jeszcze dokładniej, czy sugerowana odpowiedź na wyżej wymienione pytanie ma zastosowanie tutaj (np. Utworzyć procedurę obsługi ResolveEvent)?

Odpowiedz

8

W końcu mam na to odpowiedź, która wydaje się działać.

Skompiluj wersje 64-bitowe - zarówno zarządzane & niezarządzane - w oddzielne foldery. Następnie wybierz aplikację .NET, aby w czasie wykonywania wybrać katalog, z którego będą ładowane.

Problem z korzystaniem z narzędzia ResolveEvent polega na tym, że wywoływane jest tylko wtedy, gdy nie znaleziono zespołów, więc łatwo jest przypadkowo skończyć z wersjami 32-bitowymi. Zamiast tego użyj drugiego obiektu AppDomain, w którym możemy zmienić właściwość ApplicationBase, aby wskazywała właściwy folder. Więc skończyć z kodu, takich jak:

static void Main(String[] argv) 
    { 
    // Create a new AppDomain, but with the base directory set to either the 32-bit or 64-bit 
    // sub-directories. 

    AppDomainSetup objADS = new AppDomainSetup(); 

    System.String assemblyDir = System.IO.Path.GetDirectoryName(Application.ExecutablePath); 
    switch (System.IntPtr.Size) 
    { 
     case (4): assemblyDir += "\\win32\\"; 
      break; 
     case (8): assemblyDir += "\\x64\\"; 
      break; 
    } 

    objADS.ApplicationBase = assemblyDir; 

    // We set the PrivateBinPath to the application directory, so that we can still 
    // load the platform neutral assemblies from the app directory. 
    objADS.PrivateBinPath = System.IO.Path.GetDirectoryName(Application.ExecutablePath); 

    AppDomain objAD = AppDomain.CreateDomain("", null, objADS); 
    if (argv.Length > 0) 
     objAD.ExecuteAssembly(argv[0]); 
    else 
     objAD.ExecuteAssembly("MyApplication.exe"); 

    AppDomain.Unload(objAD); 

    } 

skończyć z 2 EXE - normalnej aplikacji i drugiego przełączania aplikacji, które wybiera, które bity do załadowania. Uwaga - Nie mogę wziąć kredytu za szczegóły tego osobiście. Jeden z moich kolegów zafascynował mnie, biorąc pod uwagę moją pierwszą wskazówkę. Jeśli i kiedy zarejestruje się do StackOverflow, przydzielę mu odpowiedź:

1

Napotkałem podobny scenariusz jakiś czas temu. Zestaw narzędzi, którego używałem, nie zachowywał się dobrze w 64-bitowym środowisku i nie byłam w stanie znaleźć sposobu na dynamiczne wymuszenie zestawów do powiązania w postaci 32-bitowej.

Możliwe jest wymuszenie pracy złożeń w trybie 32-bitowym, ale wymaga to poprawienia nagłówka CLR (istnieje narzędzie, które robi to w ramach programu) i jeśli twoje złożenia mają silną nazwę, to nie odrobić.

Obawiam się, że trzeba będzie zbudować i opublikować dwa zestawy plików binarnych dla platform 32- i 64-bitowych.

3

Mogłem to zrobić około rok temu, ale nie pamiętam już wszystkich szczegółów. Zasadniczo, możesz użyć IntPtr.Size, aby określić, która biblioteka DLL ma zostać załadowana, a następnie przeprowadź rzeczywistą metodę LoadLibrary przez p/Invoke. W tym momencie masz moduł w pamięci i powinieneś móc tylko p/Wywołać funkcje z jego wnętrza - ta sama nazwa modułu nie powinna zostać ponownie wczytana.

Myślę jednak, że w mojej aplikacji faktycznie miałem DLL C++ zarejestrować się jako serwer COM, a następnie dostęp do jego funkcjonalności poprzez wygenerowany wrapper .NET - więc nie wiem, czy kiedykolwiek testowałem p/Wywoływanie bezpośrednio.