在一个程序中组合 32 位和 64 位 DLL
Combine 32- and 64bit DLLs in one program
我需要加载 .dll 文件中提供的不同硬件驱动程序。
问题似乎是一个设备的驱动程序是在 64 位 dll 中给出的,另一个设备(相当旧)显然依赖于 32 位 dll 中给出的驱动程序。我想通过一个用 C# 编写的程序来控制它们,该程序将 运行 通过 python 包装器。
显然我不能 运行 直接从一个程序中使用两个设备,但我需要一种方法来根据彼此解决它们 - 例如:设备 1 等待设备 2 完成一些工作。有什么方法可以避免这个问题,或者我需要 运行 它们在两个单独的程序中并通过 python 包装器管理彼此依赖的操作吗?
是的,您将需要 2 个独立的进程,运行 来自不同的可执行文件。只有 32 位可执行文件可以加载 32 位 DLL。 (请参阅@MichaelPetch 的回答以获取有用的建议,详细了解如何使用可以模拟从 64 位代码调用 32 位函数或从 64 位代码调用 32 位函数的远程过程调用机制与另一个进行通信。)
x86 32 位和 x86-64 是两个不同的体系结构,它们恰好可以在不同的模式下由相同的 CPU 执行。 他们的机器-代码非常相似但不兼容,许多其他东西也不同,包括目标文件格式和 ABI 详细信息,如指针宽度为 8 字节与 4 字节。
让一个 64 位进程启动一个 线程 对 32 位代码段执行 jmp far
在技术上是可行的(因为 GDT 有 32 和 64 -bit 代码段条目),但这太疯狂了,非常 包括 DLL 动态加载/符号解析代码在内的所有内容都对它的支持很差。 (还包括内核,所以这甚至不安全:如果您尝试这样做,中断或系统调用可能 return 到 64 位模式下的 32 位代码, 因为内核知道您的线程/进程以 64 位模式启动。)
您将无法说服编译器生成 32 位代码并 link 使用 64 位代码,即使您在 OS 上使用 C "safe" 做到这一点。更高级别的托管语言使其更加无法使用,即使它是 "safe" 手写 asm.
我提到这个只是为了防止你对实现这件事的技术要求感到好奇,不是因为任何人都应该这样做。
但如果安全的话,理论上您可以为 32 位 DLL 中的每个函数编写(在 asm 中手工编写)包装函数,在调用函数之前更改为 32 位模式。
显然这是早期 32 位的东西 Windows;您可以通过 OS 提供的 "thunk" 包装器从 32 位代码调用 16 位 DLL。 但是对于来自 64 位代码的 32 位 DLL 没有类似的支持,反之亦然。
在 64 位上 Windows 64 位进程不能使用 32 位 DLL,32 位进程不能使用 64 位 DLL。微软有 documented 这个:
On 64-bit Windows, a 64-bit process cannot load a 32-bit dynamic-link library (DLL). Additionally, a 32-bit process cannot load a 64-bit DLL.
您需要一个与 32 位 DLL 通信的 32 位进程和一个与 64 位 DLL 通信的 64 位进程。微软是这样说的:
However, 64-bit Windows supports remote procedure calls (RPC) between 64-bit and 32-bit processes (both on the same computer and across computers).
问题就变成了如何让 Python 与这些进程通信的问题之一。需要某种形式的进程间通信 (IPC)。微软在几十年前创造了一项可以做到这一点的技术——使用进程外 COM 服务器(进程外)的 COM 接口。
大意是:
- 创建一个 64 位进程外 COM 服务器,它包装(并公开)64 位 DLL 所需的方法和数据。
- 创建一个 32 位进程外 COM 服务器,包装(并公开)32 位 DLL 所需的方法和数据。
- 编写实例化 COM 对象并调用其接口的 32 位或 64 位客户端代码。 Python 可以通过 win32com
用作 COM 客户端
COM 在后台提供了一种 IPC 机制,允许 64 位客户端访问 64 位进程外 COM 服务器,并允许 64 位客户端访问 32 位进程外 COM 服务器进程服务器。您甚至可以让 32 位客户端与 32 位和 64 位进程外 COM 服务器通信。
我还没有使用较新的 MS 语言完成低级 Windows 工作。当我不得不做你在问题中需要的事情时,使编写 COM 服务器和 COM 接口变得容易的两种主要技术是:
- MSVC/C++ 使用 Microsoft Foundation Classes (MFC)
- MSVC/C++ 使用 Active Template Library (ATL)。
我有一个用于 ATL 的 preference,因为它不需要 MFC 库并且开销较小。
我需要加载 .dll 文件中提供的不同硬件驱动程序。 问题似乎是一个设备的驱动程序是在 64 位 dll 中给出的,另一个设备(相当旧)显然依赖于 32 位 dll 中给出的驱动程序。我想通过一个用 C# 编写的程序来控制它们,该程序将 运行 通过 python 包装器。
显然我不能 运行 直接从一个程序中使用两个设备,但我需要一种方法来根据彼此解决它们 - 例如:设备 1 等待设备 2 完成一些工作。有什么方法可以避免这个问题,或者我需要 运行 它们在两个单独的程序中并通过 python 包装器管理彼此依赖的操作吗?
是的,您将需要 2 个独立的进程,运行 来自不同的可执行文件。只有 32 位可执行文件可以加载 32 位 DLL。 (请参阅@MichaelPetch 的回答以获取有用的建议,详细了解如何使用可以模拟从 64 位代码调用 32 位函数或从 64 位代码调用 32 位函数的远程过程调用机制与另一个进行通信。)
x86 32 位和 x86-64 是两个不同的体系结构,它们恰好可以在不同的模式下由相同的 CPU 执行。 他们的机器-代码非常相似但不兼容,许多其他东西也不同,包括目标文件格式和 ABI 详细信息,如指针宽度为 8 字节与 4 字节。
让一个 64 位进程启动一个 线程 对 32 位代码段执行 jmp far
在技术上是可行的(因为 GDT 有 32 和 64 -bit 代码段条目),但这太疯狂了,非常 包括 DLL 动态加载/符号解析代码在内的所有内容都对它的支持很差。 (还包括内核,所以这甚至不安全:如果您尝试这样做,中断或系统调用可能 return 到 64 位模式下的 32 位代码, 因为内核知道您的线程/进程以 64 位模式启动。)
您将无法说服编译器生成 32 位代码并 link 使用 64 位代码,即使您在 OS 上使用 C "safe" 做到这一点。更高级别的托管语言使其更加无法使用,即使它是 "safe" 手写 asm.
我提到这个只是为了防止你对实现这件事的技术要求感到好奇,不是因为任何人都应该这样做。
但如果安全的话,理论上您可以为 32 位 DLL 中的每个函数编写(在 asm 中手工编写)包装函数,在调用函数之前更改为 32 位模式。
显然这是早期 32 位的东西 Windows;您可以通过 OS 提供的 "thunk" 包装器从 32 位代码调用 16 位 DLL。 但是对于来自 64 位代码的 32 位 DLL 没有类似的支持,反之亦然。
在 64 位上 Windows 64 位进程不能使用 32 位 DLL,32 位进程不能使用 64 位 DLL。微软有 documented 这个:
On 64-bit Windows, a 64-bit process cannot load a 32-bit dynamic-link library (DLL). Additionally, a 32-bit process cannot load a 64-bit DLL.
您需要一个与 32 位 DLL 通信的 32 位进程和一个与 64 位 DLL 通信的 64 位进程。微软是这样说的:
However, 64-bit Windows supports remote procedure calls (RPC) between 64-bit and 32-bit processes (both on the same computer and across computers).
问题就变成了如何让 Python 与这些进程通信的问题之一。需要某种形式的进程间通信 (IPC)。微软在几十年前创造了一项可以做到这一点的技术——使用进程外 COM 服务器(进程外)的 COM 接口。
大意是:
- 创建一个 64 位进程外 COM 服务器,它包装(并公开)64 位 DLL 所需的方法和数据。
- 创建一个 32 位进程外 COM 服务器,包装(并公开)32 位 DLL 所需的方法和数据。
- 编写实例化 COM 对象并调用其接口的 32 位或 64 位客户端代码。 Python 可以通过 win32com 用作 COM 客户端
COM 在后台提供了一种 IPC 机制,允许 64 位客户端访问 64 位进程外 COM 服务器,并允许 64 位客户端访问 32 位进程外 COM 服务器进程服务器。您甚至可以让 32 位客户端与 32 位和 64 位进程外 COM 服务器通信。
我还没有使用较新的 MS 语言完成低级 Windows 工作。当我不得不做你在问题中需要的事情时,使编写 COM 服务器和 COM 接口变得容易的两种主要技术是:
- MSVC/C++ 使用 Microsoft Foundation Classes (MFC)
- MSVC/C++ 使用 Active Template Library (ATL)。
我有一个用于 ATL 的 preference,因为它不需要 MFC 库并且开销较小。