Каков наилучший способ поддержки нескольких архитектур в смешанной управляемой / неуправляемой среде? - PullRequest
7 голосов
/ 21 июля 2010

Фон

У нас есть библиотека .NET, которая ссылается на одну из наших неуправляемых библиотек, скажем:

  • DotNet.dll
  • Unmanaged.dll

Пока что Unmanaged.dll является только 32-разрядным, поэтому DotNet.dll помечен как 32-разрядный тип процессора.

64-битная поддержка должна быть добавлена. Как организовать dll? IL-код DotNet.dll будет одинаковым как для 32-разрядных, так и для 64-разрядных версий.

Вариант 1

  • Папка 32-битных библиотек
    • DotNet.dll, тип процессора 32-битный
    • Unmanaged.dll, скомпилированный как 32-битный
  • 64-битная папка библиотек
    • DotNet.dll, тип процессора 64-битный
    • Unamanged.dll, скомпилированный как 64-битный

В этом случае разработчик, использующий эти библиотеки, вынужден создавать 2 приложения: 32-битное и 64-битное. Но в этом случае точно известно, что происходит.

Вариант 2

Это то же самое, что и вариант 1, за исключением того, что DotNet.dll имеет тип процессора AnyCPU.

  • Папка 32-битных библиотек
    • DotNet.dll, тип процессора AnyCPU
    • Unmanaged.dll, скомпилированный как 32-битный
  • Папка 64-битных библиотек
    • DotNet.dll, тип процессора AnyCPU
    • Unamanged.dll, скомпилированный как 64-битный

Мне не нравится этот, потому что разработчик, использующий эти библиотеки, при перераспределении своего приложения не может хорошо сделать так, чтобы их приложение не зависало без установки типа CPU для их приложения:

  • Если они используют 32-битную папку библиотек, на 64-битной ОС их процесс завершится сбоем
  • Если они используют 64-битную папку библиотек, в 32-битной ОС их процесс завершится сбоем

Это делает Вариант 1 превосходящим Вариант 2.

Вариант 3

  • Unmanaged_x32.dll, скомпилированный как 32-разрядный
  • Unmanaged_x64.dll, скомпилированный как 64-битный
  • DotNet.dll, тип процессора AnyCPU

DotNet.dll во время выполнения определит, с какой разрядностью он запускается, затем вызовет правильный файл Unmanaged.dll.

Вопрос (ы)

  1. Как разработчик этих библиотек, какой вариант имеет смысл?
  2. Как разработчик, использующий библиотеку DotNet.dll, какой вариант имеет смысл?
    1. Для варианта 3, если вы используете DotNet.dll, хотите ли вы знать, что библиотека во время выполнения определяет, какой Unmanaged.dll использовать?
    2. Как насчет перераспределения вашего приложения с этими библиотеками?
  3. Не хватает какой-нибудь опции?

Ответы [ 3 ]

4 голосов
/ 26 июля 2010

Я бы выбрал вариант 3, скомпилировал управляемую сборку для AnyCPU и назвал неуправляемые сборки для их архитектуры.Я вижу две отдельные проблемы, которые влияют на это решение:

Должна ли управляемая сборка быть скомпилирована для AnyCPU или конкретной архитектуры?

Я думаю, что разработчики .NET не ожидали бы ссылки на отдельнуюфайл для каждой архитектуры.Я бы использовал AnyCPU для того, чтобы иметь ровно одну dll.

Должны ли dll быть названы явно для их архитектуры?

Если вы используете AnyCPU для управляемой сборки, то здесь точно одна dll, поэтомуэто спорный вопрос.

Для неуправляемой сборки может ожидаться, что файлы, скомпилированные для разных архитектур, имеют разные имена.С технической точки зрения, присвоение имен файлам по-разному позволяет поместить файлы для обеих архитектур в один и тот же каталог;это означает вызов другого файла во время выполнения в зависимости от архитектуры, но это не является огромным бременем.Я бы назвал файлы по-другому.

2 голосов
/ 26 июля 2010

Что я делаю так:

Я отправляю DotNet.dll, скомпилированный для AnyCPU с переносимыми директивами P / Invoke (как должны быть объявления API).

Я отправляю unmanaged_32.binи unmanaged_64.bin и установите только правильный для архитектуры файл unmanaged.dll во время установки.

Фокус, который все еще работает, заключается в установке unmanaged.dll следующим образом:

x86: C: \ Program Files (x86) \ Common Files \ unmanaged.dll x64: C: \ Program Files \ Common Files \ unmanaged.dll

Если C: \ Program Files \ Common Files находится в системном пути, этозаставит P / Invoke автоматически получить правильную DLL.

2 голосов
/ 21 июля 2010

Вариант 3 кажется самым простым, а Вариант 1 - самым безопасным. С точки зрения того, какую библиотеку вызывать, не кажется, что ими будет сложно управлять, если вы не имеете дело с огромным количеством вызовов. Основная проблема заключается в том, что вам придется объявлять любую заданную функцию дважды, используя разные имена для 32- и 64-разрядных версий, а затем просто изменить атрибут DllImport, чтобы он указывал на правильную цель. Ваша функция-заглушка должна решить во время выполнения, какую из них вызвать.

Обратите внимание, что, если не считать логистику, нет необходимости включать и в папку вашей библиотеки. Пока вы не вызовете «неправильную» библиотеку, исключение этого не окажет никакого влияния.

...