简而言之:你不能将32位的应用程序链接到64位的库中。你可以在64位操作系统上运行32位应用程序,使用32位共享库(至少对于所有流行的32/64位处理器,如AMD、Intel和Sparc)。但是这并不涉及任何库。更详细的答案是:我曾经参与(在边缘)设计x86 64位Linux内核的一些团队。关于如何在技术上使这项工作发生,有一些短暂的讨论(与整个项目相比,这些讨论持续了相当长的时间)。这个问题的简要总结是,在64位中有一些在32位中不可用的寄存器。还存在内存地址和寄存器中额外32位的问题。只要库本身“知道”它是一个32位兼容库,所有这些问题都可以得到解决。但是,那么我们基本上就有了一个被编写成32位库的64位库,并且我们失去了重点。“更多寄存器”可能不适用于某些处理器,但是寄存器的更大地址/位范围绝对适用于所有32位和64位兼容处理器。我不知道是否有任何单个处理器允许32位代码调用64位共享库或静态库。除非代码专门编写以处理此问题,否则它根本行不通,这有悖于具有支持32位应用程序的通用64位库的目的。编辑:以上讨论链接一个可执行单元(例如可执行文件、共享库或静态库)。它必须是全部“一位性”,要么是32位的,要么是64位的 - 不能混合使用。当一个进程与另一个进程通信时(例如一个GUI应用程序显示来自非GUI进程的状态),只要两个进程使用相同的协议[通常,IPC不允许传递指针,因此32位/64位转换并不是一个大问题],您可以有一个进程是32位的,另一个进程是64位的。
是的,但这是一个很大的麻烦。首先,内核(kernel)与库(library)不同。通常,库在你的进程虚拟地址空间中可见;它与你自己的代码共享地址空间。调用库程序只是一个子例程调用。相比之下,要从内核请求服务,你的进程需要执行特殊指令来生成一个陷阱(trap)。这个陷阱会导致处理器执行一些特殊操作,包括将你的进程寄存器和其他状态保存在内存中(或在你通常无法访问的特殊处理器寄存器中),改变处理器中的各种模式,使它们适合于内核,并将程序计数器改变为指向内核的指令。然后内核正在运行。此时,内核可能在64位模式下运行,而你的进程在32位模式下运行。但是,内核被设计为了解这些区别。当内核检查你的进程以查看你的请求时,它会查找信息和数据结构,知道你的进程是在32位模式下运行的。内核可以支持32位和64位进程,它只是会分别处理每种类型的进程。当然,这假定你使用的64位内核支持32位进程。通常,当你调用库时,你希望它与你的代码处于相同的模式,因为普通库调用只是一个子例程调用;它不会生成陷阱,并且不会改变处理器模式。如果有必要从32位进程中调用64位库中的例程,那么你可以创建一个帮助器64位进程。你的32位进程会将库调用请求打包并通过某种形式的进程间通信发送到64位帮助器进程。该帮助器进程将调用库例程并将结果发送回来。当然,这会给每个库调用增加重大开销,因此只有在没有更好的选择且非常需要时才应这样做。
我正在开发一个可以实现此功能的应用程序。应用程序的核心是x64(使用Qt),但必须与某些设备通信,该设备只提供了来自制造商的32位库。我实现的方法是有两个应用程序,64位用于核心和GUI,32位用于控制设备并使用QSharedMemory与主应用程序通信。两个应用程序都基于Qt(分别为64位和32位)。
如果你使用的是Windows系统,那么编译为32位的应用程序可以在Windows 64位主机上运行:看一下内置在64位Windows中的WOW64子系统。话虽如此,你不能混合编译为32位和64位的代码。这意味着一个编译为32位的库无法与64位代码链接,反之亦然(不同的调用约定、堆栈帧布局、异常展开等)。