为什么ctypes.addressof()使用python2和python3给出不同的结果

时间:2019-07-19 10:35:16

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

最近,我正尝试从python2转换为python3,在我的代码中,有一些有关读取具有硬件形式的数据的工作,这些硬件具有.py接口文件,称为外部.dll库。数据由.dll和python例程之间的内存共享,具体而言,ctypes.creat_string_buffer()和ctypes.addressof()在python2.7 env下正常运行,但在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()函数的输出应该是近似的,但实际上不是。有些人可以帮助我指出例程或我有什么毛病! >

1 个答案:

答案 0 :(得分:0)

[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 (在发布模式下):
    • 对于 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 (或朋友)分配的某些内存的地址等于(或接近)某个值的事实是一个坏主意。 依赖于这种假设的代码很糟糕(可能会说这等同于未定义行为)。