ctypes,python3.8:OSError:异常:访问冲突写入0x00000000
Posted
技术标签:
【中文标题】ctypes,python3.8:OSError:异常:访问冲突写入0x00000000【英文标题】:ctypes, python3.8 : OSError: exception: access violation writing 0x00000000 【发布时间】:2020-06-15 23:26:02 【问题描述】:我想通过 python 3.8 运行一个 dll 我的 dll 部分中有一个函数:
void DLLAPI __stdcall GenerateReport (
int SeqContext,
char* szHost,
char* szDBName,
char* szUser,
char* szPasswd,
const char* szUut_Result_Id,
char szStylesheet[MAX_PATHNAME_LEN],
char szDestinationDir[MAX_DIRNAME_LEN],
char szPrefix[MAX_FILENAME_LEN],
char szFileName[MAX_PATHNAME_LEN],
char szPathName[MAX_PATHNAME_LEN],
short* psErrorOccurred,
long* plErrorCode,
char szErrorMessage[1024]
);
对于 python 部分,我这样做了:
def PrintReport():
szNom_PV_Court = ''
szErrormessage = ''
sErrorok = 0
lErrorcode = 0
worker_ = cdll.LoadLibrary("D:\\users\\Worker.dll")
if (worker_ == 0):
print( " Could not open file DLL")
worker_.GenerateReport( 0, "localhost" , "backend" , "user" , "test12", str( Uut_Result_Id ) , "D:\\users\\py\\ResourceFiles\\Gen.xsl" , "D:\\users\\py","" ,szNom_PV_Court , "D:\\users\\py" ,sErrorok ,lErrorcode ,szErrormessage )
当我执行我的代码时,我得到错误:OSError:异常:访问冲突写入 0x0000000
我不明白这个错误请帮忙
【问题讨论】:
【参考方案1】:像 Python 3 中的 "localhost"
这样的字符串是 Unicode 字符串,由 ctypes 转换为 wchar_t*
。将b'localhost'
用于转换为char*
的字节字符串。
另外,为您的函数定义 .argtypes
和 .restype
以使 ctypes 正确编组您的参数:
worker_.argtypes = c_int,c_char_p,c_char_p,c_char_p,c_char_p,c_char_p,c_char_p,c_char_p,c_char_p,c_char_p,c_char_p,POINTER(c_short),POINTER(c_long),c_char_p
worker_.restype = None
您的调用中也只有 13 个参数,但为函数定义了 14 个。
对short*
和long*
使用以下内容来创建可以传递给调用的实例。现在你传递一个零作为默认的c_int
,这可能是空指针异常的来源。
sErrorok = c_short()
lErrorcode = c_long()
使用byref(sErrorok)
和byref(lErrorcode)
调用以作为指针传递给调用。
这是一个完整的例子。我跳过了许多输入字符串,只显示一个以供参考:
test.c
#include <stdio.h>
#include <string.h>
#define DLLAPI __declspec(dllexport)
void DLLAPI __stdcall GenerateReport (
int SeqContext,
char* szHost,
short* psErrorOccurred,
long* plErrorCode,
char szErrorMessage[1024]
)
printf("SeqContext = %d szHost = %s\n",SeqContext,szHost);
*psErrorOccurred = 5;
*plErrorCode = 123;
strcpy_s(szErrorMessage,1024,"error message");
test.py
from ctypes import *
szNom_PV_Court = ''
szErrormessage = ''
sErrorok = 0
lErrorcode = 0
dll = WinDLL('./test.dll')
dll.GenerateReport.argtypes = c_int,c_char_p,POINTER(c_short),POINTER(c_long),c_char_p
dll.GenerateReport.restype = None
err_occurred = c_short()
errcode = c_long()
errmsg = create_string_buffer(1024)
dll.GenerateReport(7,b'localhost',byref(err_occurred),byref(errcode),errmsg)
print(err_occurred.value,errcode.value,errmsg.value.decode())
输出:
SeqContext = 7 szHost = localhost
5 123 error message
【讨论】:
感谢您的回答,但是当我想打印消息时 szErrormessage 仍然为空。我认为这与声明变量有关。我确实喜欢这个 szErrormessage = "" 并且对于 generateReport 函数我做了 c_char_p( szErrormessage.encode('utf-8') ) 但是当我想打印 print( szErrormessage.encode('utf-8') ) 答案仍然是空的 是不是 : szErrormessage = c_char_p() 用于声明,就像您为 sErrorok 和 lErrorcode 所做的那样? @TheRightszErrormessage = create_string_buffer(1024)
将为返回字符串分配一个缓冲区。 szErrormessage = c_char_p()
将分配一个初始化为 NULL 的指针。任何其他输出字符串也应该为其分配内存。
对于声明我确实像你说的那样:szErrormessage = create_string_buffer(1024) 和对于 generateReport 方法我让像 GenerateReport(....,szErrormessage)。但是当我打印(szErrormessage)时,输出是:您没有为 DLL 填充所有字符串,因此它们被初始化为零。您的 dll 正试图从地址 0x0(零)读取,并因此被操作系统击中。用适当的值填写所有必填字段。
【讨论】:
以上是关于ctypes,python3.8:OSError:异常:访问冲突写入0x00000000的主要内容,如果未能解决你的问题,请参考以下文章
Python Ctypes OSError:异常:访问冲突读取0x00000000
ctypes,python3.5,OSError:异常:访问冲突写入 0x00000000
PYTHON - Ctypes:OSError:异常:访问冲突写入0xFFFFFFFFFA1C001B
python3.8 load dll OSError: [WinError 127] The specified procedure could not be found
OSError:Windows 10 中的 [WinError 10013] 错误
Linux上使用pip 安装mysqlclient,pip install mysqlclient==2.0.1遇到的问题:OSError: mysql_config not found