我偶然发现了一个令人困惑的问题。在尝试使用ctypes.CDLL("libX11.so")
热修复VTK手动关闭XDisplay时,我尝试使用Python提供的XDisplay地址。这在Python3.8上运行良好,但在Python3.7上导致了一个错误。下面的代码演示如何解决在VTK中创建的XDisplay的问题。具体而言:
disp_id = self.ren_win.GetGenericDisplayId()
disp_id_int = int(disp_id[1:].split('_')[0], 16)
print(disp_id, disp_id_int)
x11 = ctypes.CDLL("libX11.so")
x11.XCloseDisplay(disp_id_int)
当运行时,返回:
user@host:~/tmp$ python3.7 tmp19.py
0000558f843c5930_p_void 94074887231792
Current thread 0x00007f8145824740 (most recent call first):
File "/home/alex/python/pyvista/pyvista/plotting/plotting.py", line 2769 in close
File "/home/alex/python/pyvista/pyvista/plotting/plotting.py", line 4207 in show
user@host:~/tmp$ python3.8 tmp19.py
0000000003568de0_p_void 56004064
如您所见,Python3.8中的地址可以与libX11.so
一起使用,但不能与Python3.7一起关闭XDisplay窗口
如注释中所述,Python返回的内存地址始终与当前Python进程相关。但是,如果是这种情况,为什么某些版本的Python会返回非常大的id(True)
地址,这是Python初始化时创建的结构。更令人困惑的是,返回这些大值的Python版本在与"libX11.so"
库接口时也会产生分段值
以下是Python 3.5-Python 3.9的结果:
user@host:~$ python3.5 -c "print(id(True))"
93962585975264
user@host:~$ python3.6 -c "print(id(True))"
10302848
user@host:~$ python3.7 -c "print(id(True))"
94134164615424
user@host:~$ python3.8 -c "print(id(True))"
11498848
user@host:~$ python3.9 -c "print(id(True))"
11374464
两个问题:
结果表明,问题在于指针为>;在我的64位Linux环境中使用4GB,这与使用ctypes包装库时的默认行为不兼容。重复@MarkTolonen的评论:
诀窍是将argtype设置为
c_void_p
:在Python3.8上,这对我有效的原因是指针的地址恰好小到可以作为int32传递,而在Python3.7上,正好整数对于int32太大。相反,将其作为
ctypes.c_void_p
传递解决了这个问题取决于cpython implementation detail,
id(...)
函数返回PyObject
的内存地址在cpython中,} structs :
Py_True
和Py_False
是macros, pointing at global instances of ^{实际的definition of these structs:
C全局变量的内存地址由编译器、链接器和动态加载程序确定,根据常量值存在未定义的行为
相关问题 更多 >
编程相关推荐