Способы доступа к 32-битной DLL из 64-битного exe
У меня есть проект, который должен быть скомпилирован и запущен в режиме 64 бит. К сожалению, мне необходимо вызвать DLL, доступную только в 32-битном режиме, поэтому я не могу разместить все в одном проекте Visual Studio. Я работаю над тем, чтобы найти лучший способ обернуть 32-битную DLL в свой собственный exe/service и выпустить удаленный (хотя и на тот же компьютер) вызов этого exe/service из моего 64-битного приложения. Моя ОС - 64-разрядная версия Win7 Pro.
Необходимые вызовы для этого 32-битного процесса - несколько десятков в секунду, но низкий объем данных. Это приложение для анализа изображений в реальном времени, поэтому время отклика является критическим, несмотря на низкий уровень громкости. Множество отправных/принимающих одиночных примитивов.
В идеале я бы разместил службу WCF для размещения этой DLL, но в 64-битной ОС нельзя заставить службу работать как x86! Источник. Это очень неудачно, так как я назначил функции вызовам службы WCF только на 4 мс на моей машине.
Я экспериментировал с именованными каналами .net. Я нашел их в 40-50 раз медленнее, чем WCF (непригодным для меня).
Любые другие варианты или предложения для наилучшего способа приблизиться к моей загадке?
Ответы
Ответ 1
Как вы правильно заметили, нет способа смешать битту в том же процессе. Вам потребуется отдельный процесс для вашей 32-битной части.
Я думаю, что хостинг WCF-сервиса - это правильный путь. Ваша ссылка говорит только о wcfsvchost. Я уверен, что вы можете создать свою собственную службу Windows и разместить службу WCF на 32-разрядной версии.
Смотрите эту ссылку: Как разместить службу WCF в управляемом приложении. Вы можете разместить свою службу в любом управляемом приложении, в том числе в службе Windows, и запускать его под нужную вам битту.
Это количество кода, необходимого для самостоятельной установки службы WCF в вашем приложении, при условии, что вы только что создали новую службу под названием MyService, и соответствующая конфигурация была добавлена в app.config:
class Program
{
static void Main(string[] args)
{
using(ServiceHost host = new ServiceHost(typeof(MyService), new Uri[0]))
{
host.Open();
Console.ReadKey();
}
}
}
Вышеупомянутая программа будет работать точно также, также если вы ее скомпилируете явно 32 или 64 бит.
Ответ 2
Отсутствует. Точка. 32-разрядная dll в 64-битном процессе = нет.
То, что я делаю, это запустить 32-битный процесс-обертку и обмениваться с ним с помощью WCF - как и вы. Я могу заставить ОС работать 32 бит.
У меня есть основная библиотека (Tradex.Connectivity.Core), с независимым от платформы .NET-кодом. У меня есть две оболочки (Wrapper32.exe, Wapper64.exe), которые запускают и загружают независимый код, а затем загружают класс (управляемый С++). Работает как шарм.
Это для меня единственный способ - вы не можете загружать 32 и 64-разрядные элементы.
Ответ 3
Я знаю, что этот ответ может быть немного запоздалым, но некоторое время назад я столкнулся с такой же проблемой (загрузка 32-разрядной DLL в сборку AnyCPU на 64-битной машине).
В качестве решения я написал LegacyWrapper. Он в основном состоит из 32-разрядной обертки exe, загружающей желаемую DLL, обмениваясь информацией с вашим приложением через именованные каналы.
Вызов будет выглядеть так:
// Define delegate matching api function
private delegate int GetSystemMetrics(int index);
// Create new WrapperClient
// Remember to ensure a call to the Dispose()-Method!
using (var client = new WrapperClient())
{
// Make calls providing library name, function name, and parameters
int x = (int)client.Invoke<GetSystemMetrics>("User32.dll", "GetSystemMetrics", new object[] { 0 });
int y = (int)client.Invoke<GetSystemMetrics>("User32.dll", "GetSystemMetrics", new object[] { 1 });
}
Для некоторых деталей вы можете обратиться к этому сообщению .
Изменить: Начиная с версии 2.1, LegacyWrapper также поддерживает загрузку 64-битных DLL из 32-битного процесса.