WindowsError:异常:使用从 C++ 到 Python 的 ctypes 创建 DLL 时出现访问冲突或 Windows 错误 193

Posted

技术标签:

【中文标题】WindowsError:异常:使用从 C++ 到 Python 的 ctypes 创建 DLL 时出现访问冲突或 Windows 错误 193【英文标题】:WindowsError: exception: access violation or Windows Error 193 when creating a DLL using ctypes from C++ to Python 【发布时间】:2018-05-03 21:03:56 【问题描述】:

我从 PyCharm 收到此错误: WindowsError:异常:访问冲突读取 0x000000504D414C43

它只出现在 Pycharm 中。当我从 Windows Powershell 运行 python 脚本时,它显示 WindowsError: [Error 193] %1 is not a valid Win32 application。我检查了调试器并且正在传递一个值,但它有时会出错给我空指针。起初,我以为我在用完数组,但即使我只返回 7(如您在底部看到的那样)并注释掉所有代码,它仍然会按照描述进行。

问题:

1) 你有什么解决办法吗?

2) 我是否正确设置了 DLL?

3)有什么建议吗?

非常感谢您的帮助。

这是我的 C++ 代码:

#include <iostream>
#include <string>
#include <array>

#include "external_lists.h"

extern creation_object A1[];
extern creation_object  A2[];
extern int A1size;
extern int A2size;


#define DLLEXPORT extern "C" __declspec(dllexport)

DLLEXPORT int get_creation_data(std::string needed_name)

int A1_size = ( A1size/ sizeof(A1[0])) ;

int A2_size = ( A2size / sizeof(A2[0]))  ;

for (int i = 0; i < A1_size; i++) 
    if (A1[i].name == needed_name) 
     
    return A1[i].value->section; 
    

return 7;

这是我的 python 包装器:

import os, sys, re
from ctypes import *

def get_creation_values(value_name):
  trimdll = CDLL('C:\\Documents\\creation.dll')
  return valuedll.get_creation_data(value_name)

if __name__ == "__main__":
  val = get_value('CLAMP')
  print(val)

总体目标:

我有一个无法修改但需要在 C++ 中访问的大文件。 C++ 文件中有很大的列表,我需要遍历这些列表并将值返回给 python 脚本。

【问题讨论】:

Ctypes 只理解 C 类型。您不能在函数签名中使用 std::string。 【参考方案1】:

ctypes 只理解 C 类型。您可以将字节字符串作为const char* 传递,并在需要时将其分配给std::string。这是一个完整的工作示例:

C++ 代码 (test.cpp)

#include <string>

#define DLLEXPORT extern "C" __declspec(dllexport)

DLLEXPORT int get_creation_data(const char* name) 
    std::string needed_name(name);
    if(needed_name == "Armaja")
        return 1;
    return 0;

Python 代码

from ctypes import *

def get_creation_values(value_name):
  trimdll = CDLL('test')
  trimdll.get_creation_data.argtypes = [c_char_p]
  trimdll.get_creation_data.restype = c_int
  return trimdll.get_creation_data(value_name)

if __name__ == "__main__":
  val = get_creation_values(b'Armaja')
  print(val)

输出:

1

注意如何指定 DLL 函数的参数类型和返回值。这有助于捕获错误。例如,尝试传递 Unicode 字符串 'Armaja' 而不是字节字符串 b'Armaja'(Python 3 语法):

Traceback (most recent call last):
  File "C:\test.py", line 10, in <module>
    val = get_creation_values('Armaja')
  File "C:\test.py", line 7, in get_creation_values
    return trimdll.get_creation_data(value_name)
ctypes.ArgumentError: argument 1: <class 'TypeError'>: wrong type

【讨论】:

您好,谢谢您,我不再看到该错误,并且我现在明白,当涉及到 DLL 时,参数需要 C 类型。您能否解释一下这些行:' trimdll.get_creation_data.argtypes = [c_char_p] trimdll.get_creation_data.restype = c_int ' 另外,你知道有没有办法返回一个对象?由于 C 类型似乎只知道原始类型,这可能吗?再次感谢您。 ctypes documentation 记录 argtypes 和 restype。第一个是函数的参数类型列表,第二个是返回类型。 ctypes 只处理 C 类型,所以不能返回对象。可以为 C++ 对象创建 C 接口。 SWIG 之类的工具可以自动执行此操作。

以上是关于WindowsError:异常:使用从 C++ 到 Python 的 ctypes 创建 DLL 时出现访问冲突或 Windows 错误 193的主要内容,如果未能解决你的问题,请参考以下文章

pytesseract,WindowsError: [错误2] 系统找不到指定的文件

C++从青铜到王者第二十三篇:C++异常

WindowsError:[错误 126] 找不到指定的模块

C++软件异常排查从入门到精通

从 C `goto` 错误处理范例转换到 C++ 异常处理范例

C++软件异常排查从入门到精通系列汇总