【问题标题】:why ctypes.addressof() give diifferent result using python2 and python3为什么 ctypes.addressof() 使用 python2 和 python3 给出不同的结果
【发布时间】:2019-07-19 10:35:16
【问题描述】:

最近我正在尝试从 python2 转移到 python3,在我的代码中,有一些关于从硬件读取数据的工作,这些硬件有一个 .py 接口文件调用外部 .dll 库。数据在.dll和python例程之间由内存共享,具体来说,ctypes.creat_string_buffer()和ctypes.addressof()在python2.7环境下运行正常,但在python3.6下却出现意外结果,原因似乎是 ctypes.addressof() 给出了巨大的不同地址值,不知道是什么原因?

'''python2.7 addressof()的输出

(base) C:\Users\Administrator>python
Python 2.7.15 |Anaconda, Inc.| (default, May  1 2018, 18:37:09) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from ctypes import *
>>> s = 128
>>> p = create_string_buffer(s)
>>> print(addressof(p))
50341488
>>> hex(addressof(p))
'0x3002670L'

'''

'''python3.6 addressof()的输出

(base) C:\Users\Administrator>conda activate py36

(py36) C:\Users\Administrator>python
Python 3.6.8 |Anaconda, Inc.| (default, Feb 21 2019, 18:30:04) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from ctypes import *
>>> s = 128
>>> p = create_string_buffer(s)
>>> print(addressof(p))
>>> 2241150277680
>>> hex(addressof(p))
>>> '0x209cef75830'

'''

在我看来,python2和python3下addressof()函数的输出应该是近似的,但实际上并非如此。谁能帮我指出例程的问题,或者我的问题,不胜感激!

【问题讨论】:

    标签: python python-3.x anaconda ctypes addressof


    【解决方案1】:

    [Python 3.Docs]: ctypes - A foreign function library for Python.

    ctypes.addressof 与值没有任何关系,它只是报告 ctypes 对象的底层 C 缓冲区的地址。

    关于:

    • ctypes.create_string_buffer(返回一个 ctypes.c_char 数组)
    • ctypes 如何分配对象:PyCData_MallocBuffer 依次调用 PyMem_Malloc(检查一下[Python 3.Docs]: Memory Management更多细节)
    • PyMem_Malloc(在 Release 模式下):
      • 对于 Python 2,它是一个 malloc 包装器
      • 对于 Python 3,事情更复杂,分配发生在块中,存在用户上下文,...,但最终它仍然依赖于 malloc (或其家族职能之一)

    输出

    [cfati@CFATI-5510-0:C:\WINDOWS\system32]> sopr.bat
    *** Set shorter prompt to better fit when pasted in StackOverflow (or other) pages ***
    
    [prompt]>
    [prompt]> set _PYTHON2="e:\Work\Dev\VEnvs\py_064_02.07.15_test0\Scripts\python.exe"
    
    [prompt]> set _PYTHON3="e:\Work\Dev\VEnvs\py_064_03.07.03_test0\Scripts\python.exe"
    
    [prompt]> rem PYTHON 3 - CTYPES
    
    [prompt]> %_PYTHON3% -c "from ctypes import *; print(hex(addressof(create_string_buffer(128))))"
    0x25652521230
    
    [prompt]> %_PYTHON3% -c "from ctypes import *; print(hex(addressof(create_string_buffer(128))))"
    0x25c61371230
    
    [prompt]> %_PYTHON3% -c "from ctypes import *; print(hex(addressof(create_string_buffer(128))))"
    0x20a3dfd1230
    
    [prompt]> rem PYTHON 2 - CTYPES
    
    [prompt]> %_PYTHON2% -c "from ctypes import *; print(hex(addressof(create_string_buffer(128))))"
    0x2f5f3b0L
    
    [prompt]> %_PYTHON2% -c "from ctypes import *; print(hex(addressof(create_string_buffer(128))))"
    0x262f3b0L
    
    [prompt]> %_PYTHON2% -c "from ctypes import *; print(hex(addressof(create_string_buffer(128))))"
    0x313f3b0L
    
    [prompt]>
    [prompt]> rem PYTHON 3 - REGULAR
    
    [prompt]> %_PYTHON3% -c "print(hex(id(1234567)))"
    0x1df0d6af5b0
    
    [prompt]> %_PYTHON3% -c "print(hex(id(1234567)))"
    0x14f39e7f5b0
    
    [prompt]> %_PYTHON3% -c "print(hex(id(1234567)))"
    0x1f61453f5b0
    
    [prompt]> rem PYTHON 2 - REGULAR
    
    [prompt]> %_PYTHON2% -c "print(hex(id(1234567)))"
    0x2a2ca90L
    
    [prompt]> %_PYTHON2% -c "print(hex(id(1234567)))"
    0x325c6a0L
    
    [prompt]> %_PYTHON2% -c "print(hex(id(1234567)))"
    0x28bbec0L
    

    正如所见,内存地址模式与 ctypes 对象无关,而是与所有对象相关(并且地址每次都不同)。

    请注意,依赖于一个指向由 malloc(或朋友)分配的内存的地址等于(或接近)某个值的事实是一个坏主意。 依赖此类假设的代码很糟糕(可能会说这相当于未定义的行为)。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-04-29
    • 2021-12-07
    • 2020-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-18
    相关资源
    最近更新 更多