Ctypes 问题 - 无法使用 64 位 DLL 与 32 位 DLL - OSError:异常:访问冲突读取

如何解决Ctypes 问题 - 无法使用 64 位 DLL 与 32 位 DLL - OSError:异常:访问冲突读取

经过数小时的研究和主题分析,我找不到正确的解释和方法来正确解决我的问题。 如果您找到了答案,在此先非常感谢您。

我的问题摘要

我正在使用 python 3.8(64 位版本)和 dll(也是 64 位版本)。而且,尽管由于指针问题(根据我的一点理解)具有 ctypes 功能(argstype、restype..etc),但我无法将其正确包装到我的 python 代码中。

让我烦恼的是,32 位的同一个 DLL 和 python 32 位在我的 python 代码中运行良好。

请在此之后找到:

  • C 原型
  • 封装 C 函数的 Python 代码
  • C函数在python代码中的使用

C 函数原型(来自 API 描述): WORD mpc_AddToScenarioPcd (BYTE,DWORD,POINTER(BYTE),VOID*)

我的 Python 代码来包装这个(64 位版本和 32 位版本注释):

from ctypes import *

# DLL Loading ---------------------------------------------------------------------------------------
# 64 Bits -------------------------------------------------------------------------------------------
dllpath = '%s/MP300Com64.dll' % str(os.path.dirname(__file__))
MP300Dll = WinDLL(dllpath)
MP300Dll_CDECL = CDLL(dllpath)

# 64 Bits -------------------------------------------------------------------------------------------
# dllpath = '%s/MP300Com.dll' % str(os.path.dirname(__file__))
# MP300Dll = WinDLL(dllpath)
# MP300Dll_CDECL = CDLL(dllpath)

# Keyword Type definition ---------------------------------------------------------------------------
WORD = c_ushort
DWORD = c_ulong
BYTE = c_ubyte

# Function Wrapped ----------------------------------------------------------------------------------
mpc_AddToScenarioPcd = MP300Dll_CDECL.MPC_AddToScenarioPcd
mpc_AddToScenarioPcd.argtypes = [BYTE,POINTER(DWORD)]
mpc_AddToScenarioPcd.restype = WORD

# -- Creation of the First Pointer to the array of Bytes --------------------------------------------
array1 = (BYTE* len(5))(*[BYTE(1),BYTE(2),BYTE(3),BYTE(4),BYTE(5)])
array2 = (BYTE* len(5))(*[BYTE(10),BYTE(20),BYTE(30),BYTE(40),BYTE(50)])

# -- Pointer cast of the array1 and 2 ---------------------------------------------------------------
cast(array1,POINTER(BYTE))
cast(array2,POINTER(BYTE))
 
# VOID* obj creation --------------------------------------------------------------------------------
param = c_void_p()

# -- Function Usage through Python Code -------------------------------------------------------------
mpc_AddToScenarioPcd(BYTE(0),DWORD(0),(22),DWORD(1),DWORD(2),array1,DWORD(10),array2,param)  

使用 Python 3.4(32 位版本)和 DLL 32 位

=> 一切正常,没有错误。

使用 Python 3.8(64 位版本)和 DLL 64 位

=> 我收到此异常:OSError:异常:访问冲突读取 0x000000005EC0B808

我需要使用 64 位版本,因此我被这个问题阻止了...如果有人可以向我解释我的指针(或类型用法..)在 64 位中有什么问题,并且,怎么解决,万分感谢!!

再次非常感谢您在我的主题上的所有专业知识和工作,

PS:抱歉,非功能性代码和无法重现异常

解决方法

以下是适用于 32 位和 64 位 Python 的示例 DLL 代码和最少的 ctypes 代码。请注意以下几点:

  • ctypes.wintypes 中有预定义的 Windows 类型。
  • .argtypes.restype 设置正确时,会根据需要在 Python 和 C 之间检查和转换参数和类型的数量。通常不需要额外的转换和包装。
  • CDLL 对应于 32 位 __cdecl 调用约定。 WinDLL 对应于 32 位 __stdcall。在 64 位中,只有一种调用约定。它在 Linux 和 Windows 之间的实现方式不同,但仍然只有一个,因此 CDLLWinDLL 都可以工作,但使用正确的一个以实现 32 位可移植性。

test.c

#include <windows.h>
#include <stdio.h>

__declspec(dllexport)
WORD mpc_AddToScenarioPcd(BYTE b,DWORD d1,DWORD d2,DWORD d3,DWORD d4,DWORD d5,DWORD d6,DWORD d7,LPBYTE pb1,DWORD d8,LPBYTE pb2,LPVOID pv) {
    printf("%hhu %u %u %u %u %u %u %u %p %u %p %p\n",b,d1,d2,d3,d4,d5,d6,d7,pb1,d8,pb2,pv);
    for(int i = 0; i < 5; ++i)
        printf("%hhu %hhu\n",pb1[i],pb2[i]);
    return 1234;
}

test.py

from ctypes import *
from ctypes.wintypes import *  # pre-defined Windows types

dll = CDLL('./test')
dll.mpc_AddToScenarioPcd.argtypes = BYTE,DWORD,LPBYTE,LPVOID
dll.mpc_AddToScenarioPcd.restype = WORD

b1 = (BYTE * 5)(1,2,3,4,5)
b2 = (BYTE * 5)(10,20,30,40,50)
print(f'{addressof(b1):016X} {addressof(b2):016X}')
result = dll.mpc_AddToScenarioPcd(100,1,5,6,7,b1,8,b2,None)
print(result)

输出

注意 Python 和 C 中打印的地址是相同的。

00000194D0447A90 00000194D0447C10
100 1 2 3 4 5 6 7 00000194D0447A90 8 00000194D0447C10 0000000000000000
1 10
2 20
3 30
4 40
5 50
1234

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)&gt; insert overwrite table dwd_trade_cart_add_inc &gt; select data.id, &gt; data.user_id, &gt; data.course_id, &gt; date_format(
错误1 hive (edu)&gt; insert into huanhuan values(1,&#39;haoge&#39;); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive&gt; show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 &lt;configuration&gt; &lt;property&gt; &lt;name&gt;yarn.nodemanager.res