我试图运行一个 python 代码的例子,它使用 ctypes 从库中获取一个函数。这个例子可以在 这里 找到。我按照说明进行操作,除了一个小的修改外,我使用了完全相同的代码。我一直在尝试在 Windows 10(64 位)、python 3.7(64 位)上运行它,但收到此错误消息:
Traceback (most recent call last):
File "C:/Users/gifr9302/PycharmProjects/testpytoc/myfunc.py", line 128, in <module>
libmyfunc = npct.load_library('myfunc.dll', os.path.dirname(os.path.abspath(__file__)))
File "C:\Users\gifr9302\AppData\Local\Programs\Python\Python37\lib\site-packages\numpy\ctypeslib.py", line 152, in load_library
return ctypes.cdll[libpath]
File "C:\Users\gifr9302\AppData\Local\Programs\Python\Python37\lib\ctypes__init__.py", line 431, in __getitem__
return getattr(self, name)
File "C:\Users\gifr9302\AppData\Local\Programs\Python\Python37\lib\ctypes__init__.py", line 426, in __getattr__
dll = self._dlltype(name)
File "C:\Users\gifr9302\AppData\Local\Programs\Python\Python37\lib\ctypes__init__.py", line 356, in __init__
self._handle = _dlopen(self._name, mode)
OSError: [WinError 193] %1 n’est pas une application Win32 valide
翻译:
OSError: [WinError 193] %1 is not a valid Win32 application
我试图创建一个 dll 而不是 so 文件,但仍然出现相同的错误。它似乎试图在 64 位系统上运行 32 位应用程序,但我不确定为什么。谁能帮忙?
原文由 Frédéric Girard 发布,翻译遵循 CC BY-SA 4.0 许可协议
提到 [Python.Docs]:ctypes - Python 的外部函数库(尽管这与它没有太大关系)以防万一。
底层错误是 _ERROR_BAD_EXE_FORMAT_ ( 193 , 0xC1 )。在 [MS.Docs]: System Error Codes (0-499) 中查看。这是 一般的 Win 错误(与 Python 无关)。在当前情况下(与 Python 相关),例外是它的 ( Python ) 包装器。
1.错误
错误消息令人困惑(尤其是因为 %1 占位符)。有关详细信息,请查看 [SO]:为什么 %1 很少在“%1 不是有效的 Win32 应用程序”中被替换。 .
当 Win 尝试加载它认为是可执行 ( PE ) 映像( .exe 、 .dll ……)但实际上不是时,会发生此错误。遇到这种情况的情况多种多样( 谷歌搜索 错误,会产生很多结果)。
当从文件加载图像时(存在且可读,否则错误会有所不同 - 请查看答案末尾的项目符号之一),可能会发生这种情况的原因有很多:
已下载且下载不完整
被(错误地)覆盖(或搞砸了)
由于文件系统问题而损坏
还有很多很多
2个主要用例导致此错误:
尝试运行不是 .exe 的文件( [SO]: OSError: [WinError 193] %1 不是有效的 Win32 应用程序)
尝试在进程中加载 .dll (运行 .exe )。 这是我要关注的
下面是一个虚拟可执行文件尝试加载 .dll 的示例(可能需要检查 [SO]: How to build a DLL version of libjpeg 9b? (@CristiFati 的回答) 以获取有关在 Win 上构建命令行的详细信息)。
main00.c :
输出:
import sys import os import ctypes as ct
DLL_BASE_NAME = “dll00”
def main(*argv): dll_name = os.path.join(os.path.abspath(os.path.dirname(file)), (argv[0] if argv else DLL_BASE_NAME) + “.dll”) print(“Attempting to load: [{0:s}]”.format(dll_name)) dll00 = ct.CDLL(dll_name) func00 = dll00.dll00Func00 func00.restype = ct.c_int
if name == “main”: print(“Python {0:s} {1:03d}bit on {2:s}\n”.format(” “.join(item.strip() for item in sys.version.split(”\n”)), 64 if sys.maxsize > 0x100000000 else 32, sys.platform)) rc = main(*sys.argv[1:]) print(“\nDone.”) sys.exit(rc)
#include
#if defined(_WIN32)
define DLL00_EXPORT_API __declspec(dllexport)
#else
define DLL00_EXPORT_API
#endif
DLL00_EXPORT_API size_t dll00Func00() { return sizeof(void*); }
#if defined(_WIN32)
if defined(DLL01_EXPORTS)
define DLL01_EXPORT_API __declspec(dllexport)
else
define DLL01_EXPORT_API __declspec(dllimport)
endif
#else
define DLL01_EXPORT_API
#endif
DLL01_EXPORT_API void dll01Func00();
#include
#define DLL01_EXPORTS
#include “dll01.h”
void dll01Func00() { printf(“In [%s]\n”, FUNCTION); }
#include
#if defined(_WIN32)
define DLL00_EXPORT_API __declspec(dllexport)
#else
define DLL00_EXPORT_API
#endif
#include “dll01.h”
DLL00_EXPORT_API size_t dll00Func00() { dll01Func00(); return sizeof(void*); } “`
输出:
说明显而易见:如果我没有将垃圾数据写入 _dll01032.dll 而不是将其构建为 064bit ,则会发生同样的错误,但我选择了这个变体,因为它更短。
4。结论
我将在接下来的每个项目符号中陈述的所有内容也适用于它后面的项目符号。
想象一个 .dll 依赖于其他几个 .dll ,而每个 .dll 又依赖于其他几个,依此类推……。这就是所谓的 依赖树。所以无论 这个错误发生在树的哪个位置,它都会传播到根节点(即 .dll )
作为旁注,为了检查 .dll (或 .exe )依赖性,检查 [SO]: Discover missing module using command-line (“DLL load failed” error) (@CristiFati’s answer) ,或者作为一个问题事实上,使用任何能够获取 PE 依赖信息的工具
讨论的所有内容也适用:
如果 .dll 是正在导入的扩展模块 ( .pyd )
如果由于导入另一个模块而加载 .dll
讨论的所有内容也适用于 Nix 系统,错误(和相应的消息)明显不同
5.总结
确保:
064 位 进程 仅尝试加载 064 位 .dll
032 位 进程 仅尝试加载 032 位 .dll s
否则,(几乎)肯定会陷入这种(恶劣的)情况。
此处引导的一些现实生活场景步骤:
安装软件(在本例中为 Python )
为该软件安装(创建,构建)某种插件(包含 .dll s)( 一个(扩展)模块- 在这种情况下)
虽然通常这种检查是在安装时执行的,但需要检查(如前所述),(以上)2 的 CPU 架构 必须匹配。
如果没有发生, 请更改一个以匹配另一个,并尽可能(因为可能有一些(少数)情况不是), 瞄准 064bit (因为它没有很多 032bit 的限制).在这种情况下安装(并运行) Python 064bit 。