我从64位应用程序访问了32位dll。为此我使用共享内存IPC,我做了类似的事情
TCHAR szName[]=TEXT(Path of DLL on local machine);
TCHAR szMsg[]=TEXT("abc");
HANDLE file = CreateFile(szName,
GENERIC_READ,
0,
NULL,
CREATE_NEW,
FILE_ATTRIBUTE_NORMAL,
NULL);
通过IPC共享dll是正确的方法吗? 我可以在阅读器界面访问DLL内定义的函数吗?
答案 0 :(得分:5)
根据定义,无法从64位代码调用32位函数。处理器在32位和64位模式下的行为不同。通过将代码段选择器分别设置为32位和64位模式,操作系统可以为32位和64位应用程序执行不同的操作,但这对整个应用程序来说是一个很大的开关。
32位调用与64位代码具有不同的调用约定。 (64位模式使用寄存器用于所有调用的前5-6个参数,32位模式仅使用3个参数,而不是所有函数)。通用寄存器的用法(哪些寄存器用于什么)是不同的,因此需要以32位保存的寄存器不需要64位,依此类推。
32位操作清除64位寄存器的上半部分,无论它们是否需要。因此,只需将eax
设置为5
即可更改eax
的高64位,而32位代码甚至不知道它存在。
64位模式下的指针分配在完整的64位范围内[好吧,47位,但这仍然是15位多于32位],所以你不会成为能够将任何指针传递给被调用的代码,即使不存在其他一个问题。
push
和pop
指令现在是64位(无论您是否需要),因此32位代码将保存寄存器,认为它们占用了4个字节的堆栈,它们将占用8个,这意味着堆栈指针计算中的任何偏移在被调用函数内都是错误的 - 包括公共序列:push ebp
和mov ebp, esp
,{{1现在错了。
某些说明不再可用,或仅以其他形式提供。特别是,字节值0x40-0x4f是"前缀"对于64位指令,而不是它们以前的指令。
来自您的"导入代码的任何来电"将被视为64位,因此操作系统调用,C库调用等无法正常工作。
当然,您可以阅读该文件,将其转录为64位模式,但这需要大量的工作才能找到一个理解代码的翻译器,并且可以将其翻译(因为您' d需要知道什么是实际代码,例如什么是switch语句或嵌入在代码段中的文本字符串的跳转表,这些表不应该被翻译,至少不能以相同的方式翻译。
最有可能的是,将代码重新编译为64位更容易10倍。或者将您的64位应用程序重新编译为32位(几乎可以肯定是EASIEST选项)。
答案 1 :(得分:3)
如果您不能将此dll重新编译为64位,那么您唯一的选择确实是IPC,但不是您描述它的方式。你必须编写额外的应用程序,让它命名为dllwrapper32.exe,它将加载你的32位dll并使用一些IPC方法公开它的接口。您的64位应用程序将使用此IPC方法通过dllwrapper32.exe进程与32位dll进行通信。
您还可以编写64位dll包装器,它可以在64位进程和dllwrapper32.exe之间进行通信。所以想象一下基本的想法:
^-- loads ----> [32 bit dll]
/
[dllwrapper32.exe] <---- IPC -----> [64 bit process]
现在使用64位包装器dll:
^-- loads ----> [32 bit dll]
/
[dllwrapper32.exe] <---- IPC -----> [64 bit wrapper dll]
/\
[64 bit process] - loads ----'
IPC可以是你想要的东西:
我想COM会被推荐。
所以最后 - 做了很多工作。