PYTHON-Ctypes:OSError:exception:访问冲突写入0xFFFFFFFA1C001B

PYTHON-Ctypes:OSError:exception:访问冲突写入0xFFFFFFFA1C001B,python,ctypes,dllimport,memory-mapped-files,Python,Ctypes,Dllimport,Memory Mapped Files,下面是使用内存映射将值写入内存的代码。当我试图运行代码时,我得到了错误 文件“MMF.py”,第26行,在 memcpy(pBuf、szMsg、len(szMsg)) OSError:异常:写入0xFFFFFFFA1C001B时发生访问冲突“ 最重要的是,这里有(几乎)你需要的一切:。没有解释ctypes.wintypes,但是您可以通过在Python控制台中运行dir(ctypes.wintypes)来查看其导出。注意,所有这些类型都是简单的CTypes类型,我使用它们只是为了惯例/一致性/可

下面是使用内存映射将值写入内存的代码。当我试图运行代码时,我得到了错误 文件“MMF.py”,第26行,在 memcpy(pBuf、szMsg、len(szMsg)) OSError:异常:写入0xFFFFFFFA1C001B时发生访问冲突“

最重要的是,这里有(几乎)你需要的一切:。没有解释ctypes.wintypes,但是您可以通过在Python控制台中运行
dir(ctypes.wintypes)
来查看其导出。注意,所有这些类型都是简单的CTypes类型,我使用它们只是为了惯例/一致性/可读性

您的更新代码(code00.py):

导入系统 将ctypes导入为ct 将ctypes.wintypes作为wt导入 导入mmap 导入msvcrt def主(*argv): 文件映射所有访问权=0x000F001F 无效的\u句柄\u值=-1 SHMEMSIZE=0x100 页面_READWRITE=0x04 kernel32_dll=ct.windell.kernel32 msvcrt#u dll=ct.cdll.msvcrt#要避免 CreateFileMapping=kernel32_dll.CreateFileMappingW CreateFileMapping.argtypes=(wt.HANDLE、wt.LPVOID、wt.DWORD、wt.DWORD、wt.LPCWSTR) CreateFileMapping.restype=wt.HANDLE MapViewOfFile=kernel32\u dll.MapViewOfFile MapViewOfFile.argtypes=(wt.HANDLE、wt.DWORD、wt.DWORD、wt.DWORD、ct.c_ulonglong) MapViewOfFile.restype=wt.LPVOID memcpy=msvcrt_dll.memcpy memcpy.argtypes=(ct.c\u void\u p、ct.c\u void\u p、ct.c\u size\u t) memcpy.restype=wt.LPVOID RtlCopyMemory=kernel32\u dll.RtlCopyMemory RtlCopyMemory.argtypes=(wt.LPVOID、wt.LPCVOID、ct.c_ulonglong) UnmapViewOfFile=kernel32\u dll.UnmapViewOfFile UnmapViewOfFile.argtypes=(wt.LPCVOID,) UnmapViewOfFile.restype=wt.BOOL CloseHandle=kernel32\u dll.CloseHandle CloseHandle.argtypes=(wt.HANDLE,) CloseHandle.restype=wt.BOOL GetLastError=kernel32\u dll.GetLastError 文件\u映射\u名称\u ptr=ct.c\u wchar\u p(“MyFileMappingObject”) msg=“来自Python(ctypes)进程的消息” msg_ptr=ct.c_wchar_p(msg) mapping\u handle=CreateFileMapping(无效的\u handle\u值,0,页面\u READWRITE,0,SHMEMSIZE,文件\u映射\u名称\u ptr) 打印(“映射对象句柄:0x{:016X}”。格式(映射句柄)) 如果没有映射U句柄: 打印(“无法打开文件映射对象:{:d}”。格式(GetLastError()) 提升ct.WinError() mapped\u view\u ptr=MapViewOfFile(映射句柄、文件映射、所有访问、0、0、SHMEMSIZE) 打印(“映射视图地址:0x{:016X}”。格式(映射视图ptr)) 如果未映射\u视图\u ptr: 打印(“无法映射文件:{:d}”的视图”。格式(GetLastError()) CloseHandle(映射句柄) 提升ct.WinError() 字节_len=len(msg)*ct.sizeof(ct.c_wchar) 打印(“消息长度:{:d}字符({:d}字节)”。格式(len(msg),byte_len)) memcpy(映射视图、消息、字节长度)#注释此行 RtlCopyMemory(映射的\u视图\u ptr、消息\u ptr、字节\u len) #PythonVriant shmem=mmap.mmap(0,256,“MyFileMappingObject\u ctypes”,mmap.ACCESS\u WRITE) write(b“消息Python进程”) 打印(“按一个键清除所有内存映射并退出…”) msvcrt.getch() 取消映射文件(映射视图) CloseHandle(映射句柄) shmem.close() 如果名称=“\uuuuu main\uuuuuuuu”: 打印(“Python{0:s}{1:d}位在{2:s}\n.format(“.join(sys.version.split(“\n”)中的项的item.strip()),如果sys.maxsize>0x100000000,则为64,否则为32,sys.platform)) main(*sys.argv[1:]) 打印(“\n完成”) 注释

  • 为函数添加了argtypes和restype。有关详细信息,请参见“指定所需的参数类型(函数原型)”和“返回类型”部分,当然还有函数声明部分。这是未定义的行为,尤其是在64位:

  • memcpy的第二个参数是一个Python字符串,它与memcpy期望的char*地址(更不用说在python3中,字符串是基于wchar_________________________________

  • 常数:

    • 文件映射所有访问的值为0x000F001F(从VStudio 2015打印出的值),0x04对应于文件映射读取

    • 将无效的\u句柄\u值的旧值转换为句柄时出错,将其更改为-1(如handleapi.h中所示)

  • 您正在使用c_wchar_p调用CreateFileMappingA。这将为映射对象设置一个仅由提供的字符串中的第一个字符组成的名称,因为每个wchar\u t由2个字节组成:0x00加上相应的字符值-“a”将表示为0x00 0x41(通常这是不是真的-尤其是0x00部分,但在我们的例子中,它是)-因此lpName参数中的第二个字符(由于较小的endianness)将为0x00(NUL)

  • 根据上面的页面:

    通过
    cdll.msvcrt
    访问标准C库将使用过时的库版本,该版本可能与Python使用的版本不兼容

    因此,我还添加了替换memcpy(您可以注释掉它的行,我把它放在那里只是为了显示它的工作原理),如示例()所示,您从中获取代码,并试图转换它([minwinbase.h:#36]:
    #define copymory RtlCopyMemory

  • 将命名约定更改为与Python兼容()

  • 其他(非关键)更改(输出格式、移动代码行以获得更好的结构等)

输出


您需要在这些导入上指定argtypes和restype,否则它们将默认为32位整数。不是你想要的。+你不能将本机函数与Python对象或其他对象混合使用。一些常量的使用/定义不正确。我尝试初始化argtypes,但结果仍然是错误的same@prabakars那么也许你在“声明”中犯了错误。我们看不见就说不出来
import msvcrt, mmap
import ctypes
from ctypes import *

FILE_MAP_ALL_ACCESS = 0x04
INVALID_HANDLE_VALUE = 0xFFFFFFFF
SHMEMSIZE = 256
PAGE_READWRITE = 0x04
szName = ctypes.c_wchar_p("MyFileMappingObject")
szMsg = "Message from Python(ctypes) process"

hMapObject = windll.kernel32.CreateFileMappingA(INVALID_HANDLE_VALUE,None, PAGE_READWRITE, 0, SHMEMSIZE, szName)
print("Handle:",hMapObject)
if (hMapObject == 0):
    print("Could not open file mapping object")
    raise WinError()

pBuf = windll.kernel32.MapViewOfFile(hMapObject, FILE_MAP_ALL_ACCESS,0, 0, SHMEMSIZE)
print("Buffer Starting Addr:",pBuf)
if (pBuf == 0):
    print("Could not map view of file")
    raise WinError()
else:
    print(len(szMsg))
    memcpy = cdll.msvcrt.memcpy
    memcpy(pBuf, szMsg, len(szMsg))

shmem = mmap.mmap(0, 256, "MyFileMappingObject_ctypes", mmap.ACCESS_WRITE)
shmem.write("Message Python process")

msvcrt.getch()

windll.kernel32.UnmapViewOfFile(pBuf)
windll.kernel32.CloseHandle(hMapObject)
shmem.close()
[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q048788549]> "e:\Work\Dev\VEnvs\py_pc064_03.07.06_test0\Scripts\python.exe" code00.py
Python 3.7.6 (tags/v3.7.6:43364a7ae0, Dec 19 2019, 00:42:30) [MSC v.1916 64 bit (AMD64)] 64bit on win32

Mapping object handle: 0x000000000000022C
Mapped view addr: 0x00000192912B0000
Message length: 35 chars (70 bytes)
Hit a key to clean all memory maps and exit...

Done.