Целевая 32-разрядная или 64-разрядная нативная DLL-память в зависимости от среды

У меня есть родная DLL, которая поставляется как в 32-битной, так и в 64-разрядной версиях (x86). Я хочу создать оболочку, которая работает на обеих архитектурах (любой процессор) и загружает правильную версию DLL в зависимости от текущей среды (32 бит или 64 бит во время выполнения!). Этот процесс должен происходить автоматически, так что пользователям моей DLL не нужно настраивать определенную архитектуру.

Есть ли какие-либо рекомендации по тому, как это сделать? Любые примеры, которые могли бы мне помочь?

Я нашел одно возможное решение, которое использует управляемые прокси для каждой архитектуры, а затем использует событие Assembly.Resolve для загрузки правильной версии. Однако для этого требуется, чтобы у меня было 3 управляемых сборки в дополнение к двум неуправляемым библиотекам, которые, похоже, немного переборщились.

Есть ли другое решение?

Вот решение, которое я использовал для многих проектов:

  • назовите 32-битную сборку «32-разрядным ориентированным именем». Например MyAssembly.Native.x86.dll
  • назовите 64-битную сборку с «64-битным ориентированным именем». Например MyAssembly.Native.x64.dll
  • скомпилируйте управляемую сборку как «Any Cpu»,
  • отправляйте все по тому же пути

Вот как я объявляю методы P / Invoke:

 [DllImport("MyAssembly.Native.x86.dll", EntryPoint = "MyTest")] private static extern void MyTest86(MyType myArg); [DllImport("MyAssembly.Native.x64.dll", EntryPoint = "MyTest")] private static extern void MyTest64(MyType myArg); 

И вот соответствующая функция «MyTest», которую я всегда буду использовать (другие здесь только для правильной привязки биттирования). Он имеет ту же подпись, что и другие P / Invoke:

 public static void MyTest(MyType myArg) { if (IntPtr.Size == 8) { MyTest64(myArg); return; } MyTest86(myArg); } 

Преимущества:

  • вы можете отправлять все двоичные файлы (DLL, EXE, …) по тому же пути
  • вы поддерживаете 32-битные и 64-битные процессы и операционные системы с одинаковым расположением файлов
  • вам не нужно прибегать к Win32 apis для изменения пути загрузки DLL

Неудобства:

  • у вас будет 3 объявления метода для 1 ‘реального’ метода
  • вы потеряете некоторые циклы процессора из-за теста на битту
  • в зависимости от вашего контекста, иногда вы не можете изменять имена родных DLL, поэтому вы просто не можете этого сделать

То, как я это делаю, – это p / вызвать вызов LoadLibrary перед вызовом любого из p / invokes в библиотеку.

  • Используйте битту исполняющей сборки, чтобы определить, какую версию неуправляемой DLL загружать.
  • Затем вызовите LoadLibrary чтобы загрузить его, передавая полный путь к DLL.
  • Затем, когда вы вызываете p / invokes, правильная DLL уже загружена в процесс, и p / invokes привязаны к ней.

Это зависит от неуправляемой DLL с одинаковым именем для 32 и 64 бит. Если это не так, тогда у вас проблемы. В этом случае вам может понадобиться явно связать DLL с помощью p / вызова GetProcAddress . Это совсем не забавно. Или вы реализуете вид лесов, которые Саймон описывает в своем ответе.

Взгляните на class Microsoft.WinAny.Helper и It’a DynamicNativeLibrary, который поможет вам в том, что вам нужно.

  • Передача строк из C # в C ++ DLL и обратно - минимальный пример
  • Глобальная горячая клавиша в консольном приложении
  • Прикрепите окно формы к другому окну в C #
  • pinvokestackimbalance - как я могу это исправить или отключить?
  • Как передать указатель на массив с помощью p / invoke в C #?
  • SendInput и 64 бит
  • Разблокировать файл из .net 4 c #
  • Добавить смещение в IntPtr
  • Принесите окно в WPF
  • Захват экрана на сеансе рабочего стола сервера
  • используя class, определенный в dll c ++ в коде c #
  • Interesting Posts

    В чем разница между контролируемым обучением и неконтролируемым обучением?

    Как контролировать соединения c3p0

    Как очистить БД в герою

    Как получить мостовую сеть для работы в VirtualBox с гостевой ОС Linux на хосте Mac OS X

    Перезагрузите explorer.exe в Windows 7, сохраняя все значки в системном трее?

    Может ли полный файл подкачки замедлить работу моего ПК?

    Как узнать, сколько строк кода есть в проекте Xcode?

    Инициализируются ли поля перед кодом конструктора на Java?

    Отключить использование JSON.net

    Замените символы разрыва строки с помощью в представлении ASP.NET MVC Razor

    Android-разрешение не работает, даже если я его объявил

    Подписанные и неподписанные целые числа

    Как получить доступ к разделу восстановления Windows 8 и как восстановить его на заводской образ?

    Плагин загрузки файла jQuery: Можно ли сохранить структуру загруженных папок?

    Является ли шифрование электронной почты достаточно практичным?

    Давайте будем гением компьютера.