Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python3 segfaults when using ctypes on xlib, python2 works

The following code was scrounged up on the Internet years ago and works quite well in python2. It supplies the current idle time on the X server.

import ctypes, os, subprocess
class XScreenSaverInfo( ctypes.Structure ):
    _fields_ = [("window",     ctypes.c_ulong), ("state",      ctypes.c_int), ("kind",       ctypes.c_int), ("since",      ctypes.c_ulong), ("idle",       ctypes.c_ulong), ("event_mask", ctypes.c_ulong)]

xlib = ctypes.cdll.LoadLibrary("libX11.so.6")
xss = ctypes.cdll.LoadLibrary("libXss.so.1")
display = xlib.XOpenDisplay(os.environ["DISPLAY"])
xss.XScreenSaverAllocInfo.restype = ctypes.POINTER(XScreenSaverInfo)
xssinfo = xss.XScreenSaverAllocInfo()

 xss.XScreenSaverQueryInfo(display, xlib.XDefaultRootWindow(display), xssinfo)

 xssinfo.contents.idle

I can throw this into a python2.7.10 shell and get what I want. However, doing the same on a python3.4.3 shell kicks me out with a segmentation fault in this line

xss.XScreenSaverQueryInfo(display, xlib.XDefaultRootWindow(display), xssinfo)

Is my py3 environment broken? Does py3 do something differently?

like image 926
1N4001 Avatar asked Sep 19 '26 08:09

1N4001


1 Answers

There was no significant change in Python 3's ctypes module. However in Python3 os.environ values are unicode strings, contrary to the byte strings of python2 and this causes the segmentation fault. So changing:

display = xlib.XOpenDisplay(os.environ["DISPLAY"])

To:

display = xlib.XOpenDisplay(bytes(os.environ["DISPLAY"], 'ascii'))

Fixes the segmentation fault.

If you want to have code that works both in python 2 and 3 you want to use the encode method:

display = xlib.XOpenDisplay(os.environ["DISPLAY"].encode('ascii'))
like image 176
Bakuriu Avatar answered Sep 21 '26 22:09

Bakuriu