能够从一个32位应用程序访问64位的dll吗?

14
我有一个类似于Taskbar Shuffle的Delphi应用程序,其中包括一个钩子dll。
编辑:此钩子DLL通过发送窗口消息与主应用程序通信。
我想要添加对XP和Vista x64的支持,我的初步想法是将dll转换为64位(使用FreePascal编译),但现在保留应用程序为32位(Delphi)。
32位应用程序能否访问64位dll?
编辑2:我通过LoadLibrary加载dll,所以我认为我被卡住了,因为根据下面一个答案中Lars Truijens指向的链接所述,32位进程将无法加载64位dll。
4个回答

9
只要64位DLL被一个独立的64位进程加载,并且32位进程和64位DLL之间的所有通信都是通过松散耦合的IPC类似机制进行的,操作系统可以进行编组,那么是可以做到的。
我曾经做过类似的事情。一个32位应用程序需要在DLL中实现自定义打印池添加。应用程序和打印池添加通过IPC机制进行通信(在这种情况下是指临时文件)。
在64位系统上,除了打印池拒绝加载添加DLL外,32位应用程序的一切都正常工作,因为打印池当然是一个64位进程。
解决方案就是只重新构建64位的打印池添加。不需要改变整个32位应用程序。

我正在通过LoadLibrary加载dll,因此我想我会陷入困境,因为根据Lars Truijens指向的链接所述,32位进程无法加载64位dll。 - smartins

6
我刚刚发现了这个来自CodeCentral的解决方案: http://cc.embarcadero.com/Author/802978 它允许从32位代码调用任何64位库。
这是一个复杂的解决方案,它在后台运行一个由汇编编写的64位可执行文件,然后使用内存映射文件和Windows GDI消息与它通信,以从32位Delphi进程中启动一些64位函数。
有一个示例可以加载任何64位库,然后从32位可执行文件中调用此库的任何函数。
看起来很有效。在所有情况下,代码都值得一看:技术性很强,但设计得很好!

你确定可以从32位代码调用任何64位库吗?64位库可能返回无法从32位进程访问的数据。 - user160694
这个“桥”处理许多数据类型:64位、SIMD XMM和YMM寄存器、x87甚至AVX寄存器。内存缓冲区将通过内存映射文件处理。数据以32位返回,就像从64位库接收到的一样。因此,如果您想使用从64位检索到的句柄进行操作,则可能需要稍后调用API的64位版本。由于您可以编写自己的64位函数(如果您了解一些汇编语言),因此如果默认的“桥”不足以满足您的需求,您可以对此库进行任何操作。如果您知道自己在做什么,您可以调用任何 64位库。 - Arnaud Bouchez
猜测问题可能出现在64位库返回超出32位范围的内存指针时 - 代码将需要来回复制它们,需要一个包装器来理解哪些需要映射,哪些不需要,并希望缓冲区是“静态”的且不会更改。如果您可以控制64位端上的库所做的操作,则可以实现它,但调用任何库对我来说都有点危险,这种黑客方式我不会在生产代码中使用,除非我有非常好的理由被迫以这种方式工作。 - user160694
如果您看一下这个桥梁,您会发现它能够通过将内存缓冲区的内容复制到内存映射文件中来管理指针内容的前后移动。当然,它会比直接调用慢,但是可以工作。对于调用任何库...当然会很困难,因此也很危险。这个技巧并不是为了替换Delphi 32位exe中的所有API调用,而是为了通过本地64位包装器或外部自定义库仅进行一些调用。 - Arnaud Bouchez
@ldsandon 是的,这绝对是一种黑客行为。虽然棘手,但非常强大。从性能的角度来看,这样的解决方案是有意义的,因为内存映射结构非常适合IPC。 - Arnaud Bouchez
显示剩余2条评论

6
不行。你需要编译两个版本:64位和32位。

即使钩子 DLL 的唯一任务是与主应用程序通信以发送 Windows 消息,也可以这样做吗? - smartins
不是32位的dll被加载到64位进程中,或者反过来。如果不是这种情况,那么就没有问题了。 - Lars Truijens
答案错误。如果您创建一个后台64位进程,这是现在可能的。 :) - Arnaud Bouchez
换句话说,如果你有一个64位的进程,你可以访问一个64位的DLL。这不是有点自相矛盾吗? - Jeff Hubbard

2

不可以直接调用dll,但是你可以使用COM来绕过这个问题。如果你在一个独立进程中运行dll,并与可传输的接口(例如:兼容自动化的接口)进行通信,那么它应该能够工作。根据dll的功能和集成调用表面的广度,这种方法并不总是可行,但它是一个可以实现这种情况的选项。


只有当它是一个独立进程的COM服务,比如EXE、DCOM或COM+时,才能实现。否则,COM dll将被加载到您的进程中,并且必须为相同的平台构建。 - Lars Truijens

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接