【问题标题】:Python Ctypes - loading dll throws OSError: [WinError 193] %1 is not a valid Win32 applicationPython Ctypes - 加载 dll 引发 OSError:[WinError 193] %1 不是有效的 Win32 应用程序
【发布时间】:2021-02-19 13:32:13
【问题描述】:

我尝试运行一个 python 代码示例,该示例使用 ctypes 从库中获取函数。示例可以在here 找到。我按照说明进行操作,除了一个小的修改外,我使用了完全相同的代码。我一直在尝试在 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

翻译:

<strong>OSError: [WinError 193] %1 is not a valid Win32 application</strong>

我尝试创建一个 dll 而不是一个 so 文件,但仍然遇到同样的错误。它似乎试图在 64 位系统上运行 32 位应用程序,但我不知道为什么。有人可以帮忙吗?

【问题讨论】:

标签: python c windows dll ctypes


【解决方案1】:

提及[Python.Docs]: ctypes - A foreign function library for Python(虽然这与它没有太大关系)以防万一。

基础错误是ERROR_BAD_EXE_FORMAT1930xC1)。在[MS.Docs]: System Error Codes (0-499) 中查看。这是一个一般Win错误(与Python无关)。在当前情况下(与 Python 相关),例外是对其进行 (Python) 包装器。

1。错误

错误消息令人困惑(尤其是由于 %1 占位符)。更多详情,请查看[SO]: Why is %1 rarely substituted in “%1 is not a valid Win32 application.”

Win 尝试加载它认为是可执行 (PE) 的图像(.exe)时会发生此错误。 dll, ...),但实际上并非如此。遇到这种情况有多种情况(Google搜索错误,会产生很多结果)。

从文件加载图像时发生这种情况的可能原因有很多(现有且可读,否则错误会有所不同 - 请查看答案末尾的其中一个项目符号 ):

  • 已下载,下载不完整
  • 被(错误地)覆盖(或弄乱了)
  • 由于文件系统问题而损坏
  • 还有很多

2 个主要用例导致此错误:

  1. 试图运行一个不是 .exe 的文件 ([SO]: OSError: [WinError 193] %1 is not a valid Win32 application)
  2. 试图在进程中加载​​ .dll(运行 .exe)。 这是我要重点关注的一个

下面是一个虚拟可执行文件尝试加载 .dll 的示例。

main00.c

#include <stdio.h>
#include <Windows.h>


int main()
{
    DWORD gle = 0;
    HMODULE hMod = LoadLibraryA(".\\dll00.dll");
    if (hMod == NULL) {
        gle = GetLastError();
        printf("LoadLibrary failed: %d (0x%08X)\n", gle, gle);
    } else {
        FreeLibrary(hMod);
    }
    return gle;
}

输出

  • 注意:我将重复使用这个 cmd 控制台,即使复制/粘贴 sn-ps 会分散在答案中
[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q057187566]> sopr.bat
### Set shorter prompt to better fit when pasted in StackOverflow (or other) pages ###

[prompt]> :: Build for 064bit
[prompt]> "c:\Install\pc032\Microsoft\VisualStudioCommunity\2017\VC\Auxiliary\Build\vcvarsall.bat" x64 > nul

[prompt]> dir /b
code00.py
dll00_v0.c
main00.c

[prompt]> cl /nologo main00.c  /link /NOLOGO /OUT:main00_064.exe
main00.c

[prompt]> :: Creating an invalid .dll
[prompt]> echo garbage> dll00.dll

[prompt]> dir /b
code00.py
dll00.dll
dll00_v0.c
main00.c
main00.obj
main00_064.exe

[prompt]> main00_064.exe
LoadLibrary failed: 193 (0x000000C1)

如所见,我创建了一个包含文本“garbage”的文件 dll00.dll,所以它是一个包含无效内容的 .dll 文件.

此错误最常见的情况是架构不匹配:

  • 064bit 进程试图加载 032bit .dll
  • 032bit 进程试图加载 064bit .dll

在上述 2 种情况下,即使 .dll 包含有效的图像(对于不同的架构),它在当前进程 PoV 中仍然是无效的。为了让事情运行OK所涉及的 2 个 CPU 架构必须匹配 (1) .

2。 Python 上下文

CTypes 在加载 .dll 时做同样的事情:它在 .dll 名称上调用 [MS.Docs]: LoadLibraryW function
所以这与 CTypes 尝试在其中加载 .dllPython 进程完全相同。

code00.py

#!/usr/bin/env python3

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

    res = func00()
    print("{0:s} returned {1:d}".format(func00.__name__, res))


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)

输出

[prompt]> :: dll00.dll still contains garbage
[prompt]>
[prompt]>
[prompt]> "e:\Work\Dev\VEnvs\py_pc064_03.07.09_test0\Scripts\python.exe" code00.py
Python 3.7.9 (tags/v3.7.9:13c94747c7, Aug 17 2020, 18:58:18) [MSC v.1900 64 bit (AMD64)] 064bit on win32

Attempting to load: [e:\Work\Dev\StackOverflow\q057187566\dll00.dll]
Traceback (most recent call last):
  File "code00.py", line 25, in <module>
    rc = main(*sys.argv[1:])
  File "code00.py", line 14, in main
    dll00 = ct.CDLL(dll_name)
  File "c:\Install\pc064\Python\Python\03.07.09\lib\ctypes\__init__.py", line 364, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: [WinError 193] %1 is not a valid Win32 application

这是 (#1) (从上面) 的示例,它尝试了所有 4 种组合。

dll00_v0.c

#include <inttypes.h>

#if defined(_WIN32)
#  define DLL00_EXPORT_API __declspec(dllexport)
#else
#  define DLL00_EXPORT_API
#endif


DLL00_EXPORT_API size_t dll00Func00()
{
    return sizeof(void*);
}

输出

[prompt]> :: Still building for 064bit from previous vcvarsall call
[prompt]>
[prompt]> cl /nologo /DDLL dll00_v0.c  /link /NOLOGO /DLL /OUT:dll00_064.dll
dll00_v0.c
   Creating library dll00_064.lib and object dll00_064.exp

[prompt]>
[prompt]> :: Build for 032bit
[prompt]> "c:\Install\pc032\Microsoft\VisualStudioCommunity\2017\VC\Auxiliary\Build\vcvarsall.bat" x86
**********************************************************************
** Visual Studio 2017 Developer Command Prompt v15.9.40
** Copyright (c) 2017 Microsoft Corporation
**********************************************************************
[vcvarsall.bat] Environment initialized for: 'x86'

[prompt]> cl /nologo /DDLL dll00_v0.c  /link /NOLOGO /DLL /OUT:dll00_032.dll
dll00_v0.c
   Creating library dll00_032.lib and object dll00_032.exp

[prompt]> dir /b *.dll
dll00.dll
dll00_032.dll
dll00_064.dll

[prompt]>
[prompt]> :: Python 064bit
[prompt]>
[prompt]> "e:\Work\Dev\VEnvs\py_pc064_03.07.09_test0\Scripts\python.exe" code00.py dll00_064
Python 3.7.9 (tags/v3.7.9:13c94747c7, Aug 17 2020, 18:58:18) [MSC v.1900 64 bit (AMD64)] 064bit on win32

Attempting to load: [e:\Work\Dev\StackOverflow\q057187566\dll00_064.dll]
dll00Func00 returned 8

Done.

[prompt]>
[prompt]> "e:\Work\Dev\VEnvs\py_pc064_03.07.09_test0\Scripts\python.exe" code00.py dll00_032
Python 3.7.9 (tags/v3.7.9:13c94747c7, Aug 17 2020, 18:58:18) [MSC v.1900 64 bit (AMD64)] 064bit on win32

Attempting to load: [e:\Work\Dev\StackOverflow\q057187566\dll00_032.dll]
Traceback (most recent call last):
  File "code00.py", line 25, in <module>
    rc = main(*sys.argv[1:])
  File "code00.py", line 14, in main
    dll00 = ct.CDLL(dll_name)
  File "c:\Install\pc064\Python\Python\03.07.09\lib\ctypes\__init__.py", line 364, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: [WinError 193] %1 is not a valid Win32 application

[prompt]>
[prompt]> :: Python 032bit
[prompt]>
[prompt]> "e:\Work\Dev\VEnvs\py_pc032_03.07.09_test0\Scripts\python.exe" code00.py dll00_032
Python 3.7.9 (tags/v3.7.9:13c94747c7, Aug 17 2020, 18:01:55) [MSC v.1900 32 bit (Intel)] 032bit on win32

Attempting to load: [e:\Work\Dev\StackOverflow\q057187566\dll00_032.dll]
dll00Func00 returned 4

Done.

[prompt]>
[prompt]> "e:\Work\Dev\VEnvs\py_pc032_03.07.09_test0\Scripts\python.exe" code00.py dll00_064
Python 3.7.9 (tags/v3.7.9:13c94747c7, Aug 17 2020, 18:01:55) [MSC v.1900 32 bit (Intel)] 032bit on win32

Attempting to load: [e:\Work\Dev\StackOverflow\q057187566\dll00_064.dll]
Traceback (most recent call last):
  File "code00.py", line 25, in <module>
    rc = main(*sys.argv[1:])
  File "code00.py", line 14, in main
    dll00 = ct.CDLL(dll_name)
  File "c:\Install\pc032\Python\Python\03.07.09\lib\ctypes\__init__.py", line 364, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: [WinError 193] %1 is not a valid Win32 application

3。奖金

在上述示例中,.dll 是通过显式调用 LoadLibrary(或 LoadLibraryEx)“按需”加载的。
另一种情况是 .exe.dll 依赖(链接到)另一个 .dll,并自动加载它当自身被加载时(尽管我几乎可以肯定 LoadLibrary - 或者可能是较低级别的函数 - 在依赖 .dll 的引擎盖下自动调用)。
在下面的示例中,dll00*.dll 依赖于 dll01*.dll
仅以032bit为例(因为这是之前操作设置的当前构建环境)。

dll01.h

#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();

dll01.c

#include <stdio.h>
#define DLL01_EXPORTS
#include "dll01.h"


void dll01Func00()
{
    printf("In [%s]\n", __FUNCTION__);
}

dll00_v1.c:(修改dll00_v0.c):

#include <inttypes.h>

#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*);
}

输出

[prompt]> :: Still building for 032bit from previous vcvarsall call
[prompt]>
[prompt]> cl /nologo /DDLL dll01.c  /link /NOLOGO /DLL /OUT:dll01_032.dll
dll01.c
   Creating library dll01_032.lib and object dll01_032.exp

[prompt]> cl /nologo /DDLL dll00_v1.c  /link /NOLOGO /DLL /OUT:dll00_032.dll
dll00_v1.c
   Creating library dll00_032.lib and object dll00_032.exp
dll00_v1.obj : error LNK2019: unresolved external symbol __imp__dll01Func00 referenced in function _dll00Func00
dll00_032.dll : fatal error LNK1120: 1 unresolved externals

[prompt]>
[prompt]> cl /nologo /DDLL dll00_v1.c  /link /NOLOGO /DLL /OUT:dll00_032.dll dll01_032.lib
dll00_v1.c
   Creating library dll00_032.lib and object dll00_032.exp

[prompt]>
[prompt]> "e:\Work\Dev\VEnvs\py_pc032_03.07.09_test0\Scripts\python.exe" code00.py dll00_032
Python 3.7.9 (tags/v3.7.9:13c94747c7, Aug 17 2020, 18:01:55) [MSC v.1900 32 bit (Intel)] 032bit on win32

Attempting to load: [e:\Work\Dev\StackOverflow\q057187566\dll00_032.dll]
In [dll01Func00]
dll00Func00 returned 4

Done.

[prompt]> :: Messing up dll01_032.dll
[prompt]> echo garbage> dll01_032.dll

[prompt]> "e:\Work\Dev\VEnvs\py_pc032_03.07.09_test0\Scripts\python.exe" code00.py dll00_032
Python 3.7.9 (tags/v3.7.9:13c94747c7, Aug 17 2020, 18:01:55) [MSC v.1900 32 bit (Intel)] 032bit on win32

Attempting to load: [e:\Work\Dev\StackOverflow\q057187566\dll00_032.dll]
Traceback (most recent call last):
  File "code00.py", line 25, in <module>
    rc = main(*sys.argv[1:])
  File "code00.py", line 14, in main
    dll00 = ct.CDLL(dll_name)
  File "c:\Install\pc032\Python\Python\03.07.09\lib\ctypes\__init__.py", line 364, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: [WinError 193] %1 is not a valid Win32 application

显而易见:如果不是将垃圾数据写入 dll01_032.dll,我会为 064bit 构建它,则会发生同样的错误,但我选择了这个变体,因为它更短。

4。结论

我将在接下来的每个项目符号中说明的所有内容也适用于它后面的内容。

  • 在上述示例中,错误发生在正在加载的 .dll 或其直接依赖项之一(间接级别 1)中。不难发现,多次应用相同的原则,行为不会改变,因此它适用于任何级别的间接。
    想象一个 .dll 依赖于其他几个 .dll,而每个 .dll 又依赖于其他几个,依此类推...。这称为依赖树。所以无论这个错误会在树的哪个位置发生,它都会传播到根节点(即.dll
  • 依赖关系树传播也适用于其他错误。另一个广泛遇到ERROR_MOD_NOT_FOUND1260x7E)。这意味着找不到具有指定名称的 .dllrestating: 或它(递归地)依赖的任何其他 .dll) .
    附带说明,为了检查 .dll(或 .exe)依赖关系,请使用Dependency Walker(较新的[GitHub]: lucasg/Dependencies)或 dumpbinVStudio 安装的一部分),或者事实上,任何能够获取 PE 依赖信息的工具
  • 讨论的所有内容也适用:
    • 如果 .dll 是正在导入的扩展模块 (.pyd)
    • 如果 .dll 由于导入另一个模块而被加载
  • 讨论的所有内容也适用于 Nix 系统,错误(和相应的消息)明显不同

【讨论】:

  • @FrédéricGirard:这回答了你的问题吗?如果是,请接受答案,以便其他人也能够承认([SO]: What should I do when someone answers my question?)。如果没有,请告诉我如何改进它,所以它会回答它。
  • 这是最权威的。很好的解释。
【解决方案2】:

正如@CristiFati 所说,这是因为

1)64 位进程尝试加载 32 位 .dll

2)32 位进程尝试加载 64 位 .dll

解决方案:

--> 我也遇到了同样的问题,注意到我的 gcc 编译器生成的是 32 位编译文件而不是 64 位。所以我更改了生成 64 位文件的编译器。

--> 你可以检查你的编译文件(.exe)是 64 位还是 32 位 --> 右键单击​​ --> 属性--> 兼容性 --> 检查兼容模式选项--> 如果如果您在列表中看到 windows xp,那么您的编译器正在生成 32 位文件,如果您没有看到 windows xp,那么您的编译器正在生成 64 位文件。

【讨论】:

    【解决方案3】:

    感谢详细的解释。

    但对于那些想要直接解决方案的人来说。 我认为您应该设置 64 位 python 版本,问题将得到解决。它对我有用。

    【讨论】:

      猜你喜欢
      • 2022-08-10
      • 2014-10-28
      • 2020-07-28
      • 1970-01-01
      • 1970-01-01
      • 2020-02-19
      • 1970-01-01
      相关资源
      最近更新 更多