0

最近我试图从 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()函数的输出应该是近似的,但实际上并非如此。有人可以帮助我指出例程有什么问题,或者与我一起,不胜感激!

4

1 回答 1

0

[Python 3.Docs]:ctypes - 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(或朋友)分配的内存的地址等于(或接近)某个值这一事实是一个坏主意。依赖这种假设的代码是不好的(可能会说这相当于Undefined Behavior)。

于 2019-07-19T13:42:39.623 回答