Сведения о вопросе

Oleksandrop

15:34, 2nd August, 2020

Теги

c#   .net   64-bit   clr   x86-64    

Как поздно привязать 32-битные/64-битные библиотеки во время выполнения

Просмотров: 461   Ответов: 3

У меня есть проблема,похожая на описанную здесь , но немного отличающаяся от нее (загрузка сборок и их зависимостей).

У меня есть C++ DLL для рендеринга 3D, который мы продаем клиентам. Для пользователей .NET мы будем иметь обертку CLR вокруг него. C++ DLL может быть построен как в 32-х, так и в 64-битных версиях, но я думаю, что это означает, что нам нужно иметь две оболочки CLR, так как CLR привязывается к конкретному DLL?

Скажем, теперь у нашего клиента есть приложение .NET, которое может быть либо 32, либо 64-битным, и что это чистое приложение .NET, которое оставляет CLR, чтобы разработать его из одного набора сборок. Вопрос в том, как код приложения может динамически выбирать между нашими 32-битными и 64-битными комбинациями CLR/DLL во время выполнения?

Даже более конкретно, применим ли предлагаемый ответ на вышеупомянутый вопрос и здесь (т. е. создать обработчик ResolveEvent)?



  Сведения об ответе

baggs

10:56, 29th August, 2020

Наконец-то у меня есть ответ на этот вопрос, который, похоже, работает.

Скомпилируйте обе 32 & 64-битные версии-обе управляемые & неуправляемые - в отдельные папки. Затем попросите приложение .NET выбрать во время выполнения, из какого каталога загружать сборки.

Проблема с использованием ResolveEvent заключается в том, что он вызывается только в том случае, если сборки не найдены, поэтому легко случайно получить 32-разрядные версии. Вместо этого используйте второй объект AppDomain, где мы можем изменить свойство ApplicationBase, чтобы указать на нужную папку. Таким образом, вы в конечном итоге с кодом, как:

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

  }

В итоге вы получаете 2 exes - ваше обычное приложение и второе приложение переключения, которое выбирает, какие биты загружать. Обратите внимание - я не могу взять на себя ответственность за детали этого самого. Один из моих коллег догадался об этом, учитывая мой первоначальный указатель. Если и когда он подпишется на StackOverflow, я назначу ему ответ


  Сведения об ответе

VERSUION

16:39, 25th August, 2020

Мне удалось сделать это около года назад, но я уже не помню всех подробностей. В принципе, вы можете использовать IntPtr.Size, чтобы определить, какой DLL загрузить, а затем выполнить фактический LoadLibrary через p/Invoke. в этот момент у вас есть модуль в памяти, и вы должны быть в состоянии просто p/вызвать функции из него-то же самое имя модуля не должно быть перезагружено снова.

Я думаю, однако, что в моем приложении я на самом деле имел C++ DLL зарегистрировать себя как сервер COM, а затем получить доступ к его функциональности через сгенерированную оболочку .NET-так что я не знаю, тестировал ли я когда-либо p/вызывание напрямую.


  Сведения об ответе

COOL

03:15, 11th August, 2020

Некоторое время назад я столкнулся с подобным сценарием. Инструментарий, который я использовал, плохо работал в 64-разрядной среде,и я не смог найти способ динамического принудительного связывания сборок как 32-разрядных.

Можно заставить ваши сборки работать в 32-разрядном режиме, но это требует исправления заголовка CLR (есть инструмент, который делает это в рамках), и если ваши сборки имеют строгие имена, это не работает.

Боюсь, вам придется создать и опубликовать два набора двоичных файлов для 32-и 64-битных платформ.


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться