summaryrefslogtreecommitdiff
path: root/demo
diff options
context:
space:
mode:
Diffstat (limited to 'demo')
-rw-r--r--demo/_curses.py1075
-rw-r--r--demo/_curses_build.py327
-rw-r--r--demo/_curses_setup.py13
-rw-r--r--demo/api.py62
-rw-r--r--demo/bsdopendirtype.py48
-rw-r--r--demo/bsdopendirtype_build.py23
-rw-r--r--demo/bsdopendirtype_setup.py13
-rw-r--r--demo/btrfs-snap.py52
-rw-r--r--demo/cffi-cocoa.py102
-rw-r--r--demo/embedding.py21
-rw-r--r--demo/embedding_test.c43
-rw-r--r--demo/extern_python.py26
-rw-r--r--demo/extern_python_varargs.py61
-rw-r--r--demo/fastcsv.py266
-rw-r--r--demo/gmp.py33
-rw-r--r--demo/gmp_build.py26
-rw-r--r--demo/manual.c166
-rw-r--r--demo/manual2.py34
-rw-r--r--demo/pwuid.py7
-rw-r--r--demo/pwuid_build.py18
-rwxr-xr-xdemo/py.cleanup31
-rw-r--r--demo/pyobj.py124
-rw-r--r--demo/readdir.py35
-rw-r--r--demo/readdir2.py35
-rw-r--r--demo/readdir2_build.py36
-rw-r--r--demo/readdir2_setup.py9
-rw-r--r--demo/readdir_build.py33
-rw-r--r--demo/readdir_ctypes.py69
-rw-r--r--demo/readdir_setup.py11
-rw-r--r--demo/recopendirtype.py50
-rw-r--r--demo/recopendirtype_build.py19
-rw-r--r--demo/setup_manual.py5
-rw-r--r--demo/winclipboard.py40
-rw-r--r--demo/winclipboard_build.py36
-rw-r--r--demo/xclient.py27
-rw-r--r--demo/xclient_build.py25
36 files changed, 3001 insertions, 0 deletions
diff --git a/demo/_curses.py b/demo/_curses.py
new file mode 100644
index 0000000..46443c2
--- /dev/null
+++ b/demo/_curses.py
@@ -0,0 +1,1075 @@
+"""Reimplementation of the standard extension module '_curses' using cffi."""
+
+import sys
+from functools import wraps
+
+from _curses_cffi import ffi, lib
+
+
+def _copy_to_globals(name):
+ globals()[name] = getattr(lib, name)
+
+
+def _setup():
+ for name in ['ERR', 'OK', 'KEY_MIN', 'KEY_MAX',
+ 'A_ATTRIBUTES', 'A_NORMAL', 'A_STANDOUT', 'A_UNDERLINE',
+ 'A_REVERSE', 'A_BLINK', 'A_DIM', 'A_BOLD', 'A_ALTCHARSET',
+ 'A_PROTECT', 'A_CHARTEXT', 'A_COLOR',
+ 'COLOR_BLACK', 'COLOR_RED', 'COLOR_GREEN', 'COLOR_YELLOW',
+ 'COLOR_BLUE', 'COLOR_MAGENTA', 'COLOR_CYAN', 'COLOR_WHITE',
+ ]:
+ _copy_to_globals(name)
+
+ if not lib._m_NetBSD:
+ _copy_to_globals('A_INVIS')
+
+ for name in ['A_HORIZONTAL', 'A_LEFT', 'A_LOW', 'A_RIGHT', 'A_TOP',
+ 'A_VERTICAL',
+ ]:
+ if hasattr(lib, name):
+ _copy_to_globals(name)
+
+ if lib._m_NCURSES_MOUSE_VERSION:
+ for name in ["BUTTON1_PRESSED", "BUTTON1_RELEASED", "BUTTON1_CLICKED",
+ "BUTTON1_DOUBLE_CLICKED", "BUTTON1_TRIPLE_CLICKED",
+ "BUTTON2_PRESSED", "BUTTON2_RELEASED", "BUTTON2_CLICKED",
+ "BUTTON2_DOUBLE_CLICKED", "BUTTON2_TRIPLE_CLICKED",
+ "BUTTON3_PRESSED", "BUTTON3_RELEASED", "BUTTON3_CLICKED",
+ "BUTTON3_DOUBLE_CLICKED", "BUTTON3_TRIPLE_CLICKED",
+ "BUTTON4_PRESSED", "BUTTON4_RELEASED", "BUTTON4_CLICKED",
+ "BUTTON4_DOUBLE_CLICKED", "BUTTON4_TRIPLE_CLICKED",
+ "BUTTON_SHIFT", "BUTTON_CTRL", "BUTTON_ALT",
+ "ALL_MOUSE_EVENTS", "REPORT_MOUSE_POSITION",
+ ]:
+ _copy_to_globals(name)
+
+ if not lib._m_NetBSD:
+ for key in range(lib.KEY_MIN, lib.KEY_MAX):
+ key_n = lib.keyname(key)
+ if key_n == ffi.NULL:
+ continue
+ key_n = ffi.string(key_n)
+ if key_n == b"UNKNOWN KEY":
+ continue
+ if not isinstance(key_n, str): # python 3
+ key_n = key_n.decode()
+ key_n = key_n.replace('(', '').replace(')', '')
+ globals()[key_n] = key
+
+_setup()
+
+# Do we want this?
+# version = "2.2"
+# __version__ = "2.2"
+
+
+# ____________________________________________________________
+
+
+_initialised_setupterm = False
+_initialised = False
+_initialised_color = False
+
+
+def _ensure_initialised_setupterm():
+ if not _initialised_setupterm:
+ raise error("must call (at least) setupterm() first")
+
+
+def _ensure_initialised():
+ if not _initialised:
+ raise error("must call initscr() first")
+
+
+def _ensure_initialised_color():
+ if not _initialised and _initialised_color:
+ raise error("must call start_color() first")
+
+
+def _check_ERR(code, fname):
+ if code != lib.ERR:
+ return None
+ elif fname is None:
+ raise error("curses function returned ERR")
+ else:
+ raise error("%s() returned ERR" % (fname,))
+
+
+def _check_NULL(rval):
+ if rval == ffi.NULL:
+ raise error("curses function returned NULL")
+ return rval
+
+
+def _call_lib(method_name, *args):
+ return getattr(lib, method_name)(*args)
+
+
+def _call_lib_check_ERR(method_name, *args):
+ return _check_ERR(_call_lib(method_name, *args), method_name)
+
+
+def _mk_no_return(method_name):
+ def _execute():
+ _ensure_initialised()
+ return _call_lib_check_ERR(method_name)
+ _execute.__name__ = method_name
+ return _execute
+
+
+def _mk_flag_func(method_name):
+ # This is in the CPython implementation, but not documented anywhere.
+ # We have to support it, though, even if it make me sad.
+ def _execute(flag=True):
+ _ensure_initialised()
+ if flag:
+ return _call_lib_check_ERR(method_name)
+ else:
+ return _call_lib_check_ERR('no' + method_name)
+ _execute.__name__ = method_name
+ return _execute
+
+
+def _mk_return_val(method_name):
+ def _execute():
+ return _call_lib(method_name)
+ _execute.__name__ = method_name
+ return _execute
+
+
+def _mk_w_getyx(method_name):
+ def _execute(self):
+ y = _call_lib(method_name + 'y', self._win)
+ x = _call_lib(method_name + 'x', self._win)
+ return (y, x)
+ _execute.__name__ = method_name
+ return _execute
+
+
+def _mk_w_no_return(method_name):
+ def _execute(self, *args):
+ return _call_lib_check_ERR(method_name, self._win, *args)
+ _execute.__name__ = method_name
+ return _execute
+
+
+def _mk_w_return_val(method_name):
+ def _execute(self, *args):
+ return _call_lib(method_name, self._win, *args)
+ _execute.__name__ = method_name
+ return _execute
+
+
+def _chtype(ch):
+ return int(ffi.cast("chtype", ch))
+
+def _texttype(text):
+ if isinstance(text, str):
+ return text
+ elif isinstance(text, unicode):
+ return str(text) # default encoding
+ else:
+ raise TypeError("str or unicode expected, got a '%s' object"
+ % (type(text).__name__,))
+
+
+def _extract_yx(args):
+ if len(args) >= 2:
+ return (args[0], args[1], args[2:])
+ return (None, None, args)
+
+
+def _process_args(funcname, args, count, optcount, frontopt=0):
+ outargs = []
+ if frontopt:
+ if len(args) > count + optcount:
+ # We have the front optional args here.
+ outargs.extend(args[:frontopt])
+ args = args[frontopt:]
+ else:
+ # No front optional args, so make them None.
+ outargs.extend([None] * frontopt)
+ if (len(args) < count) or (len(args) > count + optcount):
+ raise error("%s requires %s to %s arguments" % (
+ funcname, count, count + optcount + frontopt))
+ outargs.extend(args)
+ return outargs
+
+
+def _argspec(count, optcount=0, frontopt=0):
+ def _argspec_deco(func):
+ @wraps(func)
+ def _wrapped(self, *args):
+ outargs = _process_args(
+ func.__name__, args, count, optcount, frontopt)
+ return func(self, *outargs)
+ return _wrapped
+ return _argspec_deco
+
+
+# ____________________________________________________________
+
+
+class error(Exception):
+ pass
+
+
+class Window(object):
+ def __init__(self, window):
+ self._win = window
+
+ def __del__(self):
+ if self._win != lib.stdscr:
+ lib.delwin(self._win)
+
+ untouchwin = _mk_w_no_return("untouchwin")
+ touchwin = _mk_w_no_return("touchwin")
+ redrawwin = _mk_w_no_return("redrawwin")
+ insertln = _mk_w_no_return("winsertln")
+ erase = _mk_w_no_return("werase")
+ deleteln = _mk_w_no_return("wdeleteln")
+
+ is_wintouched = _mk_w_return_val("is_wintouched")
+
+ syncdown = _mk_w_return_val("wsyncdown")
+ syncup = _mk_w_return_val("wsyncup")
+ standend = _mk_w_return_val("wstandend")
+ standout = _mk_w_return_val("wstandout")
+ cursyncup = _mk_w_return_val("wcursyncup")
+ clrtoeol = _mk_w_return_val("wclrtoeol")
+ clrtobot = _mk_w_return_val("wclrtobot")
+ clear = _mk_w_return_val("wclear")
+
+ idcok = _mk_w_no_return("idcok")
+ immedok = _mk_w_no_return("immedok")
+ timeout = _mk_w_no_return("wtimeout")
+
+ getyx = _mk_w_getyx("getcur")
+ getbegyx = _mk_w_getyx("getbeg")
+ getmaxyx = _mk_w_getyx("getmax")
+ getparyx = _mk_w_getyx("getpar")
+
+ clearok = _mk_w_no_return("clearok")
+ idlok = _mk_w_no_return("idlok")
+ leaveok = _mk_w_no_return("leaveok")
+ notimeout = _mk_w_no_return("notimeout")
+ scrollok = _mk_w_no_return("scrollok")
+ insdelln = _mk_w_no_return("winsdelln")
+ syncok = _mk_w_no_return("syncok")
+
+ mvwin = _mk_w_no_return("mvwin")
+ mvderwin = _mk_w_no_return("mvderwin")
+ move = _mk_w_no_return("wmove")
+
+ if not lib._m_STRICT_SYSV_CURSES:
+ resize = _mk_w_no_return("wresize")
+
+ if lib._m_NetBSD:
+ keypad = _mk_w_return_val("keypad")
+ nodelay = _mk_w_return_val("nodelay")
+ else:
+ keypad = _mk_w_no_return("keypad")
+ nodelay = _mk_w_no_return("nodelay")
+
+ @_argspec(1, 1, 2)
+ def addch(self, y, x, ch, attr=None):
+ if attr is None:
+ attr = lib.A_NORMAL
+ ch = _chtype(ch)
+
+ if y is not None:
+ code = lib.mvwaddch(self._win, y, x, ch | attr)
+ else:
+ code = lib.waddch(self._win, ch | attr)
+ return _check_ERR(code, "addch")
+
+ @_argspec(1, 1, 2)
+ def addstr(self, y, x, text, attr=None):
+ text = _texttype(text)
+ if attr is not None:
+ attr_old = lib.getattrs(self._win)
+ lib.wattrset(self._win, attr)
+ if y is not None:
+ code = lib.mvwaddstr(self._win, y, x, text)
+ else:
+ code = lib.waddstr(self._win, text)
+ if attr is not None:
+ lib.wattrset(self._win, attr_old)
+ return _check_ERR(code, "addstr")
+
+ @_argspec(2, 1, 2)
+ def addnstr(self, y, x, text, n, attr=None):
+ text = _texttype(text)
+ if attr is not None:
+ attr_old = lib.getattrs(self._win)
+ lib.wattrset(self._win, attr)
+ if y is not None:
+ code = lib.mvwaddnstr(self._win, y, x, text, n)
+ else:
+ code = lib.waddnstr(self._win, text, n)
+ if attr is not None:
+ lib.wattrset(self._win, attr_old)
+ return _check_ERR(code, "addnstr")
+
+ def bkgd(self, ch, attr=None):
+ if attr is None:
+ attr = lib.A_NORMAL
+ return _check_ERR(lib.wbkgd(self._win, _chtype(ch) | attr), "bkgd")
+
+ attroff = _mk_w_no_return("wattroff")
+ attron = _mk_w_no_return("wattron")
+ attrset = _mk_w_no_return("wattrset")
+
+ def bkgdset(self, ch, attr=None):
+ if attr is None:
+ attr = lib.A_NORMAL
+ lib.wbkgdset(self._win, _chtype(ch) | attr)
+ return None
+
+ def border(self, ls=0, rs=0, ts=0, bs=0, tl=0, tr=0, bl=0, br=0):
+ lib.wborder(self._win,
+ _chtype(ls), _chtype(rs), _chtype(ts), _chtype(bs),
+ _chtype(tl), _chtype(tr), _chtype(bl), _chtype(br))
+ return None
+
+ def box(self, vertint=0, horint=0):
+ lib.box(self._win, vertint, horint)
+ return None
+
+ @_argspec(1, 1, 2)
+ def chgat(self, y, x, num, attr=None):
+ # These optional args are in a weird order.
+ if attr is None:
+ attr = num
+ num = -1
+
+ color = ((attr >> 8) & 0xff)
+ attr = attr - (color << 8)
+
+ if y is not None:
+ code = lib.mvwchgat(self._win, y, x, num, attr, color, ffi.NULL)
+ lib.touchline(self._win, y, 1)
+ else:
+ yy, _ = self.getyx()
+ code = lib.wchgat(self._win, num, attr, color, ffi.NULL)
+ lib.touchline(self._win, yy, 1)
+ return _check_ERR(code, "chgat")
+
+ def delch(self, *args):
+ if len(args) == 0:
+ code = lib.wdelch(self._win)
+ elif len(args) == 2:
+ code = lib.mvwdelch(self._win, *args)
+ else:
+ raise error("delch requires 0 or 2 arguments")
+ return _check_ERR(code, "[mv]wdelch")
+
+ def derwin(self, *args):
+ nlines = 0
+ ncols = 0
+ if len(args) == 2:
+ begin_y, begin_x = args
+ elif len(args) == 4:
+ nlines, ncols, begin_y, begin_x = args
+ else:
+ raise error("derwin requires 2 or 4 arguments")
+
+ win = lib.derwin(self._win, nlines, ncols, begin_y, begin_x)
+ return Window(_check_NULL(win))
+
+ def echochar(self, ch, attr=None):
+ if attr is None:
+ attr = lib.A_NORMAL
+ ch = _chtype(ch)
+
+ if lib._m_ispad(self._win):
+ code = lib.pechochar(self._win, ch | attr)
+ else:
+ code = lib.wechochar(self._win, ch | attr)
+ return _check_ERR(code, "echochar")
+
+ if lib._m_NCURSES_MOUSE_VERSION:
+ enclose = _mk_w_return_val("wenclose")
+
+ getbkgd = _mk_w_return_val("getbkgd")
+
+ def getch(self, *args):
+ if len(args) == 0:
+ val = lib.wgetch(self._win)
+ elif len(args) == 2:
+ val = lib.mvwgetch(self._win, *args)
+ else:
+ raise error("getch requires 0 or 2 arguments")
+ return val
+
+ def getkey(self, *args):
+ if len(args) == 0:
+ val = lib.wgetch(self._win)
+ elif len(args) == 2:
+ val = lib.mvwgetch(self._win, *args)
+ else:
+ raise error("getkey requires 0 or 2 arguments")
+
+ if val == lib.ERR:
+ raise error("no input")
+ elif val <= 255:
+ return chr(val)
+ else:
+ # XXX: The following line is different if `__NetBSD__` is defined.
+ val = lib.keyname(val)
+ if val == ffi.NULL:
+ return ""
+ return ffi.string(val)
+
+ @_argspec(0, 1, 2)
+ def getstr(self, y, x, n=1023):
+ n = min(n, 1023)
+ buf = ffi.new("char[1024]") # /* This should be big enough.. I hope */
+
+ if y is None:
+ val = lib.wgetnstr(self._win, buf, n)
+ else:
+ val = lib.mvwgetnstr(self._win, y, x, buf, n)
+
+ if val == lib.ERR:
+ return ""
+ return ffi.string(buf)
+
+ @_argspec(2, 1, 2)
+ def hline(self, y, x, ch, n, attr=None):
+ ch = _chtype(ch)
+ if attr is None:
+ attr = lib.A_NORMAL
+ if y is not None:
+ _check_ERR(lib.wmove(self._win, y, x), "wmove")
+ return _check_ERR(lib.whline(self._win, ch | attr, n), "hline")
+
+ @_argspec(1, 1, 2)
+ def insch(self, y, x, ch, attr=None):
+ ch = _chtype(ch)
+ if attr is None:
+ attr = lib.A_NORMAL
+ if y is not None:
+ code = lib.mvwinsch(self._win, y, x, ch | attr)
+ else:
+ code = lib.winsch(self._win, ch | attr)
+ return _check_ERR(code, "insch")
+
+ def inch(self, *args):
+ if len(args) == 0:
+ return lib.winch(self._win)
+ elif len(args) == 2:
+ return lib.mvwinch(self._win, *args)
+ else:
+ raise error("inch requires 0 or 2 arguments")
+
+ @_argspec(0, 1, 2)
+ def instr(self, y, x, n=1023):
+ n = min(n, 1023)
+ buf = ffi.new("char[1024]") # /* This should be big enough.. I hope */
+ if y is None:
+ code = lib.winnstr(self._win, buf, n)
+ else:
+ code = lib.mvwinnstr(self._win, y, x, buf, n)
+
+ if code == lib.ERR:
+ return ""
+ return ffi.string(buf)
+
+ @_argspec(1, 1, 2)
+ def insstr(self, y, x, text, attr=None):
+ text = _texttype(text)
+ if attr is not None:
+ attr_old = lib.getattrs(self._win)
+ lib.wattrset(self._win, attr)
+ if y is not None:
+ code = lib.mvwinsstr(self._win, y, x, text)
+ else:
+ code = lib.winsstr(self._win, text)
+ if attr is not None:
+ lib.wattrset(self._win, attr_old)
+ return _check_ERR(code, "insstr")
+
+ @_argspec(2, 1, 2)
+ def insnstr(self, y, x, text, n, attr=None):
+ text = _texttype(text)
+ if attr is not None:
+ attr_old = lib.getattrs(self._win)
+ lib.wattrset(self._win, attr)
+ if y is not None:
+ code = lib.mvwinsnstr(self._win, y, x, text, n)
+ else:
+ code = lib.winsnstr(self._win, text, n)
+ if attr is not None:
+ lib.wattrset(self._win, attr_old)
+ return _check_ERR(code, "insnstr")
+
+ def is_linetouched(self, line):
+ code = lib.is_linetouched(self._win, line)
+ if code == lib.ERR:
+ raise error("is_linetouched: line number outside of boundaries")
+ if code == lib.FALSE:
+ return False
+ return True
+
+ def noutrefresh(self, *args):
+ if lib._m_ispad(self._win):
+ if len(args) != 6:
+ raise error(
+ "noutrefresh() called for a pad requires 6 arguments")
+ return _check_ERR(lib.pnoutrefresh(self._win, *args),
+ "pnoutrefresh")
+ else:
+ # XXX: Better args check here? We need zero args.
+ return _check_ERR(lib.wnoutrefresh(self._win, *args),
+ "wnoutrefresh")
+
+ nooutrefresh = noutrefresh # "to be removed in 2.3", but in 2.7, 3.x.
+
+ def _copywin(self, dstwin, overlay,
+ sminr, sminc, dminr, dminc, dmaxr, dmaxc):
+ return _check_ERR(lib.copywin(self._win, dstwin._win,
+ sminr, sminc, dminr, dminc, dmaxr, dmaxc,
+ overlay), "copywin")
+
+ def overlay(self, dstwin, *args):
+ if len(args) == 6:
+ return self._copywin(dstwin, True, *args)
+ elif len(args) == 0:
+ return _check_ERR(lib.overlay(self._win, dstwin._win), "overlay")
+ else:
+ raise error("overlay requires one or seven arguments")
+
+ def overwrite(self, dstwin, *args):
+ if len(args) == 6:
+ return self._copywin(dstwin, False, *args)
+ elif len(args) == 0:
+ return _check_ERR(lib.overwrite(self._win, dstwin._win),
+ "overwrite")
+ else:
+ raise error("overwrite requires one or seven arguments")
+
+ def putwin(self, filep):
+ # filestar = ffi.new("FILE *", filep)
+ return _check_ERR(lib.putwin(self._win, filep), "putwin")
+
+ def redrawln(self, beg, num):
+ return _check_ERR(lib.wredrawln(self._win, beg, num), "redrawln")
+
+ def refresh(self, *args):
+ if lib._m_ispad(self._win):
+ if len(args) != 6:
+ raise error(
+ "noutrefresh() called for a pad requires 6 arguments")
+ return _check_ERR(lib.prefresh(self._win, *args), "prefresh")
+ else:
+ # XXX: Better args check here? We need zero args.
+ return _check_ERR(lib.wrefresh(self._win, *args), "wrefresh")
+
+ def setscrreg(self, y, x):
+ return _check_ERR(lib.wsetscrreg(self._win, y, x), "wsetscrreg")
+
+ def subwin(self, *args):
+ nlines = 0
+ ncols = 0
+ if len(args) == 2:
+ begin_y, begin_x = args
+ elif len(args) == 4:
+ nlines, ncols, begin_y, begin_x = args
+ else:
+ raise error("subwin requires 2 or 4 arguments")
+
+ if lib._m_ispad(self._win):
+ win = lib.subpad(self._win, nlines, ncols, begin_y, begin_x)
+ else:
+ win = lib.subwin(self._win, nlines, ncols, begin_y, begin_x)
+ return Window(_check_NULL(win))
+
+ def scroll(self, nlines=None):
+ if nlines is None:
+ return _check_ERR(lib.scroll(self._win), "scroll")
+ else:
+ return _check_ERR(lib.wscrl(self._win, nlines), "scroll")
+
+ def touchline(self, st, cnt, val=None):
+ if val is None:
+ return _check_ERR(lib.touchline(self._win, st, cnt), "touchline")
+ else:
+ return _check_ERR(lib.wtouchln(self._win, st, cnt, val),
+ "touchline")
+
+ @_argspec(2, 1, 2)
+ def vline(self, y, x, ch, n, attr=None):
+ ch = _chtype(ch)
+ if attr is None:
+ attr = lib.A_NORMAL
+ if y is not None:
+ _check_ERR(lib.wmove(self._win, y, x), "wmove")
+ return _check_ERR(lib.wvline(self._win, ch | attr, n), "vline")
+
+
+beep = _mk_no_return("beep")
+def_prog_mode = _mk_no_return("def_prog_mode")
+def_shell_mode = _mk_no_return("def_shell_mode")
+doupdate = _mk_no_return("doupdate")
+endwin = _mk_no_return("endwin")
+flash = _mk_no_return("flash")
+nocbreak = _mk_no_return("nocbreak")
+noecho = _mk_no_return("noecho")
+nonl = _mk_no_return("nonl")
+noraw = _mk_no_return("noraw")
+reset_prog_mode = _mk_no_return("reset_prog_mode")
+reset_shell_mode = _mk_no_return("reset_shell_mode")
+resetty = _mk_no_return("resetty")
+savetty = _mk_no_return("savetty")
+
+cbreak = _mk_flag_func("cbreak")
+echo = _mk_flag_func("echo")
+nl = _mk_flag_func("nl")
+raw = _mk_flag_func("raw")
+
+baudrate = _mk_return_val("baudrate")
+termattrs = _mk_return_val("termattrs")
+
+termname = _mk_return_val("termname")
+longname = _mk_return_val("longname")
+
+can_change_color = _mk_return_val("can_change_color")
+has_colors = _mk_return_val("has_colors")
+has_ic = _mk_return_val("has_ic")
+has_il = _mk_return_val("has_il")
+isendwin = _mk_return_val("isendwin")
+flushinp = _mk_return_val("flushinp")
+noqiflush = _mk_return_val("noqiflush")
+
+
+def filter():
+ lib.filter()
+ return None
+
+
+def color_content(color):
+ _ensure_initialised_color()
+ r, g, b = ffi.new("short *"), ffi.new("short *"), ffi.new("short *")
+ if lib.color_content(color, r, g, b) == lib.ERR:
+ raise error("Argument 1 was out of range. Check value of COLORS.")
+ return (r[0], g[0], b[0])
+
+
+def color_pair(n):
+ _ensure_initialised_color()
+ return (n << 8)
+
+
+def curs_set(vis):
+ _ensure_initialised()
+ val = lib.curs_set(vis)
+ _check_ERR(val, "curs_set")
+ return val
+
+
+def delay_output(ms):
+ _ensure_initialised()
+ return _check_ERR(lib.delay_output(ms), "delay_output")
+
+
+def erasechar():
+ _ensure_initialised()
+ return lib.erasechar()
+
+
+def getsyx():
+ _ensure_initialised()
+ yx = ffi.new("int[2]")
+ lib._m_getsyx(yx)
+ return (yx[0], yx[1])
+
+
+if lib._m_NCURSES_MOUSE_VERSION:
+
+ def getmouse():
+ _ensure_initialised()
+ mevent = ffi.new("MEVENT *")
+ _check_ERR(lib.getmouse(mevent), "getmouse")
+ return (mevent.id, mevent.x, mevent.y, mevent.z, mevent.bstate)
+
+ def ungetmouse(id, x, y, z, bstate):
+ _ensure_initialised()
+ mevent = ffi.new("MEVENT *")
+ mevent.id, mevent.x, mevent.y, mevent.z, mevent.bstate = (
+ id, x, y, z, bstate)
+ return _check_ERR(lib.ungetmouse(mevent), "ungetmouse")
+
+
+def getwin(filep):
+ return Window(_check_NULL(lib.getwin(filep)))
+
+
+def halfdelay(tenths):
+ _ensure_initialised()
+ return _check_ERR(lib.halfdelay(tenths), "halfdelay")
+
+
+if not lib._m_STRICT_SYSV_CURSES:
+ def has_key(ch):
+ _ensure_initialised()
+ return lib.has_key(ch)
+
+
+def init_color(color, r, g, b):
+ _ensure_initialised_color()
+ return _check_ERR(lib.init_color(color, r, g, b), "init_color")
+
+
+def init_pair(pair, f, b):
+ _ensure_initialised_color()
+ return _check_ERR(lib.init_pair(pair, f, b), "init_pair")
+
+
+def _mk_acs(name, ichar):
+ if len(ichar) == 1:
+ globals()[name] = lib.acs_map[ord(ichar)]
+ else:
+ globals()[name] = globals()[ichar]
+
+
+def _map_acs():
+ _mk_acs("ACS_ULCORNER", 'l')
+ _mk_acs("ACS_LLCORNER", 'm')
+ _mk_acs("ACS_URCORNER", 'k')
+ _mk_acs("ACS_LRCORNER", 'j')
+ _mk_acs("ACS_LTEE", 't')
+ _mk_acs("ACS_RTEE", 'u')
+ _mk_acs("ACS_BTEE", 'v')
+ _mk_acs("ACS_TTEE", 'w')
+ _mk_acs("ACS_HLINE", 'q')
+ _mk_acs("ACS_VLINE", 'x')
+ _mk_acs("ACS_PLUS", 'n')
+ _mk_acs("ACS_S1", 'o')
+ _mk_acs("ACS_S9", 's')
+ _mk_acs("ACS_DIAMOND", '`')
+ _mk_acs("ACS_CKBOARD", 'a')
+ _mk_acs("ACS_DEGREE", 'f')
+ _mk_acs("ACS_PLMINUS", 'g')
+ _mk_acs("ACS_BULLET", '~')
+ _mk_acs("ACS_LARROW", ',')
+ _mk_acs("ACS_RARROW", '+')
+ _mk_acs("ACS_DARROW", '.')
+ _mk_acs("ACS_UARROW", '-')
+ _mk_acs("ACS_BOARD", 'h')
+ _mk_acs("ACS_LANTERN", 'i')
+ _mk_acs("ACS_BLOCK", '0')
+ _mk_acs("ACS_S3", 'p')
+ _mk_acs("ACS_S7", 'r')
+ _mk_acs("ACS_LEQUAL", 'y')
+ _mk_acs("ACS_GEQUAL", 'z')
+ _mk_acs("ACS_PI", '{')
+ _mk_acs("ACS_NEQUAL", '|')
+ _mk_acs("ACS_STERLING", '}')
+ _mk_acs("ACS_BSSB", "ACS_ULCORNER")
+ _mk_acs("ACS_SSBB", "ACS_LLCORNER")
+ _mk_acs("ACS_BBSS", "ACS_URCORNER")
+ _mk_acs("ACS_SBBS", "ACS_LRCORNER")
+ _mk_acs("ACS_SBSS", "ACS_RTEE")
+ _mk_acs("ACS_SSSB", "ACS_LTEE")
+ _mk_acs("ACS_SSBS", "ACS_BTEE")
+ _mk_acs("ACS_BSSS", "ACS_TTEE")
+ _mk_acs("ACS_BSBS", "ACS_HLINE")
+ _mk_acs("ACS_SBSB", "ACS_VLINE")
+ _mk_acs("ACS_SSSS", "ACS_PLUS")
+
+
+def initscr():
+ if _initialised:
+ lib.wrefresh(lib.stdscr)
+ return Window(lib.stdscr)
+
+ win = _check_NULL(lib.initscr())
+ globals()['_initialised_setupterm'] = True
+ globals()['_initialised'] = True
+
+ _map_acs()
+
+ globals()["LINES"] = lib.LINES
+ globals()["COLS"] = lib.COLS
+
+ return Window(win)
+
+
+def setupterm(term=None, fd=-1):
+ if fd == -1:
+ # XXX: Check for missing stdout here?
+ fd = sys.stdout.fileno()
+
+ if _initialised_setupterm:
+ return None
+
+ if term is None:
+ term = ffi.NULL
+ err = ffi.new("int *")
+ if lib.setupterm(term, fd, err) == lib.ERR:
+ err = err[0]
+ if err == 0:
+ raise error("setupterm: could not find terminal")
+ elif err == -1:
+ raise error("setupterm: could not find terminfo database")
+ else:
+ raise error("setupterm: unknown error")
+
+ globals()["_initialised_setupterm"] = True
+ return None
+
+
+def intrflush(ch):
+ _ensure_initialised()
+ return _check_ERR(lib.intrflush(ffi.NULL, ch), "intrflush")
+
+
+# XXX: #ifdef HAVE_CURSES_IS_TERM_RESIZED
+def is_term_resized(lines, columns):
+ _ensure_initialised()
+ return lib.is_term_resized(lines, columns)
+
+
+if not lib._m_NetBSD:
+ def keyname(ch):
+ _ensure_initialised()
+ if ch < 0:
+ raise error("invalid key number")
+ knp = lib.keyname(ch)
+ if knp == ffi.NULL:
+ return ""
+ return ffi.string(knp)
+
+
+def killchar():
+ return lib.killchar()
+
+
+def meta(ch):
+ return _check_ERR(lib.meta(lib.stdscr, ch), "meta")
+
+
+if lib._m_NCURSES_MOUSE_VERSION:
+
+ def mouseinterval(interval):
+ _ensure_initialised()
+ return _check_ERR(lib.mouseinterval(interval), "mouseinterval")
+
+ def mousemask(newmask):
+ _ensure_initialised()
+ oldmask = ffi.new("mmask_t *")
+ availmask = lib.mousemask(newmask, oldmask)
+ return (availmask, oldmask)
+
+
+def napms(ms):
+ _ensure_initialised()
+ return lib.napms(ms)
+
+
+def newpad(nlines, ncols):
+ _ensure_initialised()
+ return Window(_check_NULL(lib.newpad(nlines, ncols)))
+
+
+def newwin(nlines, ncols, begin_y=None, begin_x=None):
+ _ensure_initialised()
+ if begin_x is None:
+ if begin_y is not None:
+ raise error("newwin requires 2 or 4 arguments")
+ begin_y = begin_x = 0
+
+ return Window(_check_NULL(lib.newwin(nlines, ncols, begin_y, begin_x)))
+
+
+def pair_content(pair):
+ _ensure_initialised_color()
+ f = ffi.new("short *")
+ b = ffi.new("short *")
+ if lib.pair_content(pair, f, b) == lib.ERR:
+ raise error("Argument 1 was out of range. (1..COLOR_PAIRS-1)")
+ return (f, b)
+
+
+def pair_number(pairvalue):
+ _ensure_initialised_color()
+ return (pairvalue & lib.A_COLOR) >> 8
+
+
+def putp(text):
+ text = _texttype(text)
+ return _check_ERR(lib.putp(text), "putp")
+
+
+def qiflush(flag=True):
+ _ensure_initialised()
+ if flag:
+ lib.qiflush()
+ else:
+ lib.noqiflush()
+ return None
+
+
+# XXX: Do something about the following?
+# /* Internal helper used for updating curses.LINES, curses.COLS, _curses.LINES
+# * and _curses.COLS */
+# #if defined(HAVE_CURSES_RESIZETERM) || defined(HAVE_CURSES_RESIZE_TERM)
+# static int
+# update_lines_cols(void)
+# {
+# PyObject *o;
+# PyObject *m = PyImport_ImportModuleNoBlock("curses");
+
+# if (!m)
+# return 0;
+
+# o = PyInt_FromLong(LINES);
+# if (!o) {
+# Py_DECREF(m);
+# return 0;
+# }
+# if (PyObject_SetAttrString(m, "LINES", o)) {
+# Py_DECREF(m);
+# Py_DECREF(o);
+# return 0;
+# }
+# if (PyDict_SetItemString(ModDict, "LINES", o)) {
+# Py_DECREF(m);
+# Py_DECREF(o);
+# return 0;
+# }
+# Py_DECREF(o);
+# o = PyInt_FromLong(COLS);
+# if (!o) {
+# Py_DECREF(m);
+# return 0;
+# }
+# if (PyObject_SetAttrString(m, "COLS", o)) {
+# Py_DECREF(m);
+# Py_DECREF(o);
+# return 0;
+# }
+# if (PyDict_SetItemString(ModDict, "COLS", o)) {
+# Py_DECREF(m);
+# Py_DECREF(o);
+# return 0;
+# }
+# Py_DECREF(o);
+# Py_DECREF(m);
+# return 1;
+# }
+# #endif
+
+# #ifdef HAVE_CURSES_RESIZETERM
+# static PyObject *
+# PyCurses_ResizeTerm(PyObject *self, PyObject *args)
+# {
+# int lines;
+# int columns;
+# PyObject *result;
+
+# PyCursesInitialised;
+
+# if (!PyArg_ParseTuple(args,"ii:resizeterm", &lines, &columns))
+# return NULL;
+
+# result = PyCursesCheckERR(resizeterm(lines, columns), "resizeterm");
+# if (!result)
+# return NULL;
+# if (!update_lines_cols())
+# return NULL;
+# return result;
+# }
+
+# #endif
+
+# #ifdef HAVE_CURSES_RESIZE_TERM
+# static PyObject *
+# PyCurses_Resize_Term(PyObject *self, PyObject *args)
+# {
+# int lines;
+# int columns;
+
+# PyObject *result;
+
+# PyCursesInitialised;
+
+# if (!PyArg_ParseTuple(args,"ii:resize_term", &lines, &columns))
+# return NULL;
+
+# result = PyCursesCheckERR(resize_term(lines, columns), "resize_term");
+# if (!result)
+# return NULL;
+# if (!update_lines_cols())
+# return NULL;
+# return result;
+# }
+# #endif /* HAVE_CURSES_RESIZE_TERM */
+
+
+def setsyx(y, x):
+ _ensure_initialised()
+ lib.setsyx(y, x)
+ return None
+
+
+def start_color():
+ _check_ERR(lib.start_color(), "start_color")
+ globals()["COLORS"] = lib.COLORS
+ globals()["COLOR_PAIRS"] = lib.COLOR_PAIRS
+ globals()["_initialised_color"] = True
+ return None
+
+
+def tigetflag(capname):
+ _ensure_initialised_setupterm()
+ return lib.tigetflag(capname)
+
+
+def tigetnum(capname):
+ _ensure_initialised_setupterm()
+ return lib.tigetnum(capname)
+
+
+def tigetstr(capname):
+ _ensure_initialised_setupterm()
+ val = lib.tigetstr(capname)
+ if int(ffi.cast("intptr_t", val)) in (0, -1):
+ return None
+ return ffi.string(val)
+
+
+def tparm(fmt, i1=0, i2=0, i3=0, i4=0, i5=0, i6=0, i7=0, i8=0, i9=0):
+ args = [ffi.cast("int", i) for i in (i1, i2, i3, i4, i5, i6, i7, i8, i9)]
+ result = lib.tparm(fmt, *args)
+ if result == ffi.NULL:
+ raise error("tparm() returned NULL")
+ return ffi.string(result)
+
+
+def typeahead(fd):
+ _ensure_initialised()
+ return _check_ERR(lib.typeahead(fd), "typeahead")
+
+
+def unctrl(ch):
+ _ensure_initialised()
+ return lib.unctrl(_chtype(ch))
+
+
+def ungetch(ch):
+ _ensure_initialised()
+ return _check_ERR(lib.ungetch(_chtype(ch)), "ungetch")
+
+
+def use_env(flag):
+ lib.use_env(flag)
+ return None
+
+
+if not lib._m_STRICT_SYSV_CURSES:
+
+ def use_default_colors():
+ _ensure_initialised_color()
+ return _check_ERR(lib.use_default_colors(), "use_default_colors")
diff --git a/demo/_curses_build.py b/demo/_curses_build.py
new file mode 100644
index 0000000..1a1a3ec
--- /dev/null
+++ b/demo/_curses_build.py
@@ -0,0 +1,327 @@
+import sys
+if sys.platform == 'win32':
+ #This module does not exist in windows
+ raise ImportError('No module named _curses')
+
+from cffi import FFI
+
+ffi = FFI()
+
+ffi.cdef("""
+typedef ... WINDOW;
+typedef ... SCREEN;
+typedef unsigned long... mmask_t;
+typedef unsigned char bool;
+typedef unsigned long... chtype;
+typedef chtype attr_t;
+
+typedef struct
+{
+ short id; /* ID to distinguish multiple devices */
+ int x, y, z; /* event coordinates (character-cell) */
+ mmask_t bstate; /* button state bits */
+}
+MEVENT;
+
+static const int ERR, OK;
+static const int TRUE, FALSE;
+static const int KEY_MIN, KEY_MAX;
+
+static const int COLOR_BLACK;
+static const int COLOR_RED;
+static const int COLOR_GREEN;
+static const int COLOR_YELLOW;
+static const int COLOR_BLUE;
+static const int COLOR_MAGENTA;
+static const int COLOR_CYAN;
+static const int COLOR_WHITE;
+
+static const chtype A_ATTRIBUTES;
+static const chtype A_NORMAL;
+static const chtype A_STANDOUT;
+static const chtype A_UNDERLINE;
+static const chtype A_REVERSE;
+static const chtype A_BLINK;
+static const chtype A_DIM;
+static const chtype A_BOLD;
+static const chtype A_ALTCHARSET;
+static const chtype A_INVIS;
+static const chtype A_PROTECT;
+static const chtype A_CHARTEXT;
+static const chtype A_COLOR;
+
+static const int BUTTON1_RELEASED;
+static const int BUTTON1_PRESSED;
+static const int BUTTON1_CLICKED;
+static const int BUTTON1_DOUBLE_CLICKED;
+static const int BUTTON1_TRIPLE_CLICKED;
+static const int BUTTON2_RELEASED;
+static const int BUTTON2_PRESSED;
+static const int BUTTON2_CLICKED;
+static const int BUTTON2_DOUBLE_CLICKED;
+static const int BUTTON2_TRIPLE_CLICKED;
+static const int BUTTON3_RELEASED;
+static const int BUTTON3_PRESSED;
+static const int BUTTON3_CLICKED;
+static const int BUTTON3_DOUBLE_CLICKED;
+static const int BUTTON3_TRIPLE_CLICKED;
+static const int BUTTON4_RELEASED;
+static const int BUTTON4_PRESSED;
+static const int BUTTON4_CLICKED;
+static const int BUTTON4_DOUBLE_CLICKED;
+static const int BUTTON4_TRIPLE_CLICKED;
+static const int BUTTON_SHIFT;
+static const int BUTTON_CTRL;
+static const int BUTTON_ALT;
+static const int ALL_MOUSE_EVENTS;
+static const int REPORT_MOUSE_POSITION;
+
+int setupterm(char *, int, int *);
+
+WINDOW *stdscr;
+int COLORS;
+int COLOR_PAIRS;
+int COLS;
+int LINES;
+
+int baudrate(void);
+int beep(void);
+int box(WINDOW *, chtype, chtype);
+bool can_change_color(void);
+int cbreak(void);
+int clearok(WINDOW *, bool);
+int color_content(short, short*, short*, short*);
+int copywin(const WINDOW*, WINDOW*, int, int, int, int, int, int, int);
+int curs_set(int);
+int def_prog_mode(void);
+int def_shell_mode(void);
+int delay_output(int);
+int delwin(WINDOW *);
+WINDOW * derwin(WINDOW *, int, int, int, int);
+int doupdate(void);
+int echo(void);
+int endwin(void);
+char erasechar(void);
+void filter(void);
+int flash(void);
+int flushinp(void);
+chtype getbkgd(WINDOW *);
+WINDOW * getwin(FILE *);
+int halfdelay(int);
+bool has_colors(void);
+bool has_ic(void);
+bool has_il(void);
+void idcok(WINDOW *, bool);
+int idlok(WINDOW *, bool);
+void immedok(WINDOW *, bool);
+WINDOW * initscr(void);
+int init_color(short, short, short, short);
+int init_pair(short, short, short);
+int intrflush(WINDOW *, bool);
+bool isendwin(void);
+bool is_linetouched(WINDOW *, int);
+bool is_wintouched(WINDOW *);
+const char * keyname(int);
+int keypad(WINDOW *, bool);
+char killchar(void);
+int leaveok(WINDOW *, bool);
+char * longname(void);
+int meta(WINDOW *, bool);
+int mvderwin(WINDOW *, int, int);
+int mvwaddch(WINDOW *, int, int, const chtype);
+int mvwaddnstr(WINDOW *, int, int, const char *, int);
+int mvwaddstr(WINDOW *, int, int, const char *);
+int mvwchgat(WINDOW *, int, int, int, attr_t, short, const void *);
+int mvwdelch(WINDOW *, int, int);
+int mvwgetch(WINDOW *, int, int);
+int mvwgetnstr(WINDOW *, int, int, char *, int);
+int mvwin(WINDOW *, int, int);
+chtype mvwinch(WINDOW *, int, int);
+int mvwinnstr(WINDOW *, int, int, char *, int);
+int mvwinsch(WINDOW *, int, int, chtype);
+int mvwinsnstr(WINDOW *, int, int, const char *, int);
+int mvwinsstr(WINDOW *, int, int, const char *);
+int napms(int);
+WINDOW * newpad(int, int);
+WINDOW * newwin(int, int, int, int);
+int nl(void);
+int nocbreak(void);
+int nodelay(WINDOW *, bool);
+int noecho(void);
+int nonl(void);
+void noqiflush(void);
+int noraw(void);
+int notimeout(WINDOW *, bool);
+int overlay(const WINDOW*, WINDOW *);
+int overwrite(const WINDOW*, WINDOW *);
+int pair_content(short, short*, short*);
+int pechochar(WINDOW *, const chtype);
+int pnoutrefresh(WINDOW*, int, int, int, int, int, int);
+int prefresh(WINDOW *, int, int, int, int, int, int);
+int putwin(WINDOW *, FILE *);
+void qiflush(void);
+int raw(void);
+int redrawwin(WINDOW *);
+int resetty(void);
+int reset_prog_mode(void);
+int reset_shell_mode(void);
+int savetty(void);
+int scroll(WINDOW *);
+int scrollok(WINDOW *, bool);
+int start_color(void);
+WINDOW * subpad(WINDOW *, int, int, int, int);
+WINDOW * subwin(WINDOW *, int, int, int, int);
+int syncok(WINDOW *, bool);
+chtype termattrs(void);
+char * termname(void);
+int touchline(WINDOW *, int, int);
+int touchwin(WINDOW *);
+int typeahead(int);
+int ungetch(int);
+int untouchwin(WINDOW *);
+void use_env(bool);
+int waddch(WINDOW *, const chtype);
+int waddnstr(WINDOW *, const char *, int);
+int waddstr(WINDOW *, const char *);
+int wattron(WINDOW *, int);
+int wattroff(WINDOW *, int);
+int wattrset(WINDOW *, int);
+int wbkgd(WINDOW *, chtype);
+void wbkgdset(WINDOW *, chtype);
+int wborder(WINDOW *, chtype, chtype, chtype, chtype,
+ chtype, chtype, chtype, chtype);
+int wchgat(WINDOW *, int, attr_t, short, const void *);
+int wclear(WINDOW *);
+int wclrtobot(WINDOW *);
+int wclrtoeol(WINDOW *);
+void wcursyncup(WINDOW *);
+int wdelch(WINDOW *);
+int wdeleteln(WINDOW *);
+int wechochar(WINDOW *, const chtype);
+int werase(WINDOW *);
+int wgetch(WINDOW *);
+int wgetnstr(WINDOW *, char *, int);
+int whline(WINDOW *, chtype, int);
+chtype winch(WINDOW *);
+int winnstr(WINDOW *, char *, int);
+int winsch(WINDOW *, chtype);
+int winsdelln(WINDOW *, int);
+int winsertln(WINDOW *);
+int winsnstr(WINDOW *, const char *, int);
+int winsstr(WINDOW *, const char *);
+int wmove(WINDOW *, int, int);
+int wresize(WINDOW *, int, int);
+int wnoutrefresh(WINDOW *);
+int wredrawln(WINDOW *, int, int);
+int wrefresh(WINDOW *);
+int wscrl(WINDOW *, int);
+int wsetscrreg(WINDOW *, int, int);
+int wstandout(WINDOW *);
+int wstandend(WINDOW *);
+void wsyncdown(WINDOW *);
+void wsyncup(WINDOW *);
+void wtimeout(WINDOW *, int);
+int wtouchln(WINDOW *, int, int, int);
+int wvline(WINDOW *, chtype, int);
+int tigetflag(char *);
+int tigetnum(char *);
+char * tigetstr(char *);
+int putp(const char *);
+char * tparm(const char *, ...);
+int getattrs(const WINDOW *);
+int getcurx(const WINDOW *);
+int getcury(const WINDOW *);
+int getbegx(const WINDOW *);
+int getbegy(const WINDOW *);
+int getmaxx(const WINDOW *);
+int getmaxy(const WINDOW *);
+int getparx(const WINDOW *);
+int getpary(const WINDOW *);
+
+int getmouse(MEVENT *);
+int ungetmouse(MEVENT *);
+mmask_t mousemask(mmask_t, mmask_t *);
+bool wenclose(const WINDOW *, int, int);
+int mouseinterval(int);
+
+void setsyx(int y, int x);
+const char *unctrl(chtype);
+int use_default_colors(void);
+
+int has_key(int);
+bool is_term_resized(int, int);
+
+#define _m_STRICT_SYSV_CURSES ...
+#define _m_NCURSES_MOUSE_VERSION ...
+#define _m_NetBSD ...
+int _m_ispad(WINDOW *);
+
+chtype acs_map[];
+
+// For _curses_panel:
+
+typedef ... PANEL;
+
+WINDOW *panel_window(const PANEL *);
+void update_panels(void);
+int hide_panel(PANEL *);
+int show_panel(PANEL *);
+int del_panel(PANEL *);
+int top_panel(PANEL *);
+int bottom_panel(PANEL *);
+PANEL *new_panel(WINDOW *);
+PANEL *panel_above(const PANEL *);
+PANEL *panel_below(const PANEL *);
+int set_panel_userptr(PANEL *, void *);
+const void *panel_userptr(const PANEL *);
+int move_panel(PANEL *, int, int);
+int replace_panel(PANEL *,WINDOW *);
+int panel_hidden(const PANEL *);
+
+void _m_getsyx(int *yx);
+""")
+
+
+ffi.set_source("_curses_cffi", """
+#ifdef __APPLE__
+/* the following define is necessary for OS X 10.6+; without it, the
+ Apple-supplied ncurses.h sets NCURSES_OPAQUE to 1, and then Python
+ can't get at the WINDOW flags field. */
+#define NCURSES_OPAQUE 0
+#endif
+
+#include <ncurses.h>
+#include <panel.h>
+#include <term.h>
+
+#if defined STRICT_SYSV_CURSES
+#define _m_STRICT_SYSV_CURSES TRUE
+#else
+#define _m_STRICT_SYSV_CURSES FALSE
+#endif
+
+#if defined NCURSES_MOUSE_VERSION
+#define _m_NCURSES_MOUSE_VERSION TRUE
+#else
+#define _m_NCURSES_MOUSE_VERSION FALSE
+#endif
+
+#if defined __NetBSD__
+#define _m_NetBSD TRUE
+#else
+#define _m_NetBSD FALSE
+#endif
+
+int _m_ispad(WINDOW *win) {
+ // <curses.h> may not have _flags (and possibly _ISPAD),
+ // but for now let's assume that <ncurses.h> always has it
+ return (win->_flags & _ISPAD);
+}
+
+void _m_getsyx(int *yx) {
+ getsyx(yx[0], yx[1]);
+}
+""", libraries=['ncurses', 'panel'])
+
+if __name__ == '__main__':
+ ffi.compile()
diff --git a/demo/_curses_setup.py b/demo/_curses_setup.py
new file mode 100644
index 0000000..ec3d20e
--- /dev/null
+++ b/demo/_curses_setup.py
@@ -0,0 +1,13 @@
+from setuptools import setup
+
+setup(
+ name="_curses",
+ version="0.1",
+ py_modules=["_curses"],
+ setup_requires=["cffi>=1.0.dev0"],
+ cffi_modules=[
+ "_curses_build.py:ffi",
+ ],
+ install_requires=["cffi>=1.0.dev0"], # should maybe be "cffi-backend" only?
+ zip_safe=False,
+)
diff --git a/demo/api.py b/demo/api.py
new file mode 100644
index 0000000..8cc6407
--- /dev/null
+++ b/demo/api.py
@@ -0,0 +1,62 @@
+import cffi
+from cffi import FFI
+
+class PythonFFI(FFI):
+
+ def __init__(self, backend=None):
+ FFI.__init__(self, backend=backend)
+ self._pyexports = {}
+
+ def pyexport(self, signature):
+ tp = self._typeof(signature, consider_function_as_funcptr=True)
+ def decorator(func):
+ name = func.__name__
+ if name in self._pyexports:
+ raise cffi.CDefError("duplicate pyexport'ed function %r"
+ % (name,))
+ callback_var = self.getctype(tp, name)
+ self.cdef("%s;" % callback_var)
+ self._pyexports[name] = _PyExport(tp, func)
+ return decorator
+
+ def verify(self, source='', **kwargs):
+ extras = []
+ pyexports = sorted(self._pyexports.items())
+ for name, export in pyexports:
+ callback_var = self.getctype(export.tp, name)
+ extras.append("%s;" % callback_var)
+ extras.append(source)
+ source = '\n'.join(extras)
+ lib = FFI.verify(self, source, **kwargs)
+ for name, export in pyexports:
+ cb = self.callback(export.tp, export.func)
+ export.cb = cb
+ setattr(lib, name, cb)
+ return lib
+
+
+class _PyExport(object):
+ def __init__(self, tp, func):
+ self.tp = tp
+ self.func = func
+
+
+if __name__ == '__main__':
+ ffi = PythonFFI()
+
+ @ffi.pyexport("int(int)")
+ def add1(n):
+ print n
+ return n + 1
+
+ ffi.cdef("""
+ int f(int);
+ """)
+
+ lib = ffi.verify("""
+ int f(int x) {
+ return add1(add1(x));
+ }
+ """)
+
+ assert lib.f(5) == 7
diff --git a/demo/bsdopendirtype.py b/demo/bsdopendirtype.py
new file mode 100644
index 0000000..75a996a
--- /dev/null
+++ b/demo/bsdopendirtype.py
@@ -0,0 +1,48 @@
+from _bsdopendirtype import ffi, lib
+
+
+def _posix_error():
+ raise OSError(ffi.errno, os.strerror(ffi.errno))
+
+_dtype_to_smode = {
+ lib.DT_BLK: 0o060000,
+ lib.DT_CHR: 0o020000,
+ lib.DT_DIR: 0o040000,
+ lib.DT_FIFO: 0o010000,
+ lib.DT_LNK: 0o120000,
+ lib.DT_REG: 0o100000,
+ lib.DT_SOCK: 0o140000,
+}
+
+def opendir(dir):
+ if len(dir) == 0:
+ dir = b'.'
+ dirname = dir
+ if not dirname.endswith(b'/'):
+ dirname += b'/'
+ dirp = lib.opendir(dir)
+ if dirp == ffi.NULL:
+ raise _posix_error()
+ try:
+ while True:
+ ffi.errno = 0
+ dirent = lib.readdir(dirp)
+ if dirent == ffi.NULL:
+ if ffi.errno != 0:
+ raise _posix_error()
+ return
+ name = ffi.string(dirent.d_name)
+ if name == b'.' or name == b'..':
+ continue
+ name = dirname + name
+ try:
+ smode = _dtype_to_smode[dirent.d_type]
+ except KeyError:
+ smode = os.lstat(name).st_mode
+ yield name, smode
+ finally:
+ lib.closedir(dirp)
+
+if __name__ == '__main__':
+ for name, smode in opendir(b'/tmp'):
+ print(hex(smode), name)
diff --git a/demo/bsdopendirtype_build.py b/demo/bsdopendirtype_build.py
new file mode 100644
index 0000000..3c5bb0b
--- /dev/null
+++ b/demo/bsdopendirtype_build.py
@@ -0,0 +1,23 @@
+from cffi import FFI
+
+ffibuilder = FFI()
+ffibuilder.cdef("""
+ typedef ... DIR;
+ struct dirent {
+ unsigned char d_type; /* type of file */
+ char d_name[]; /* filename */
+ ...;
+ };
+ DIR *opendir(const char *name);
+ int closedir(DIR *dirp);
+ struct dirent *readdir(DIR *dirp);
+ static const int DT_BLK, DT_CHR, DT_DIR, DT_FIFO, DT_LNK, DT_REG, DT_SOCK;
+""")
+
+ffibuilder.set_source("_bsdopendirtype", """
+ #include <sys/types.h>
+ #include <dirent.h>
+""")
+
+if __name__ == '__main__':
+ ffibuilder.compile(verbose=True)
diff --git a/demo/bsdopendirtype_setup.py b/demo/bsdopendirtype_setup.py
new file mode 100644
index 0000000..30a6cfb
--- /dev/null
+++ b/demo/bsdopendirtype_setup.py
@@ -0,0 +1,13 @@
+from setuptools import setup
+
+setup(
+ name="example",
+ version="0.1",
+ py_modules=["bsdopendirtype"],
+ setup_requires=["cffi>=1.0.dev0"],
+ cffi_modules=[
+ "bsdopendirtype_build.py:ffibuilder",
+ ],
+ install_requires=["cffi>=1.0.dev0"], # should maybe be "cffi-backend" only?
+ zip_safe=False,
+)
diff --git a/demo/btrfs-snap.py b/demo/btrfs-snap.py
new file mode 100644
index 0000000..fceeaa1
--- /dev/null
+++ b/demo/btrfs-snap.py
@@ -0,0 +1,52 @@
+"""
+btrfs-snap.py: source target newname
+
+creates a exactly named snapshots and bails out if they exist
+"""
+
+import argparse
+import fcntl
+import os
+import sys
+
+import cffi
+
+ffi = cffi.FFI()
+
+ffi.cdef("""
+ #define BTRFS_IOC_SNAP_CREATE_V2 ...
+ struct btrfs_ioctl_vol_args_v2 {
+ int64_t fd;
+ char name[];
+ ...;
+ };
+""")
+
+ffi.set_source("_btrfs_cffi", "#include <btrfs/ioctl.h>")
+ffi.compile()
+
+# ____________________________________________________________
+
+
+from _btrfs_cffi import ffi, lib
+
+parser = argparse.ArgumentParser(usage=__doc__.strip())
+parser.add_argument('source', help='source subvolume')
+parser.add_argument('target', help='target directory')
+parser.add_argument('newname', help='name of the new snapshot')
+opts = parser.parse_args()
+
+source = os.open(opts.source, os.O_DIRECTORY)
+target = os.open(opts.target, os.O_DIRECTORY)
+
+
+args = ffi.new('struct btrfs_ioctl_vol_args_v2 *')
+args.name = opts.newname
+args.fd = source
+args_buffer = ffi.buffer(args)
+try:
+ fcntl.ioctl(target, lib.BTRFS_IOC_SNAP_CREATE_V2, args_buffer)
+except IOError as e:
+ print e
+ sys.exit(1)
+
diff --git a/demo/cffi-cocoa.py b/demo/cffi-cocoa.py
new file mode 100644
index 0000000..9e86d99
--- /dev/null
+++ b/demo/cffi-cocoa.py
@@ -0,0 +1,102 @@
+# Based on http://cocoawithlove.com/2010/09/minimalist-cocoa-programming.html
+# by Juraj Sukop. This demo was eventually expanded into a more complete
+# Cocoa library available at https://bitbucket.org/sukop/nspython .
+
+from cffi import FFI
+
+ffi = FFI()
+ffi.cdef('''
+
+ typedef signed char BOOL;
+
+ typedef long NSInteger;
+ typedef unsigned long NSUInteger;
+ typedef NSInteger NSApplicationActivationPolicy;
+ typedef NSUInteger NSBackingStoreType;
+ typedef NSUInteger NSStringEncoding;
+
+ typedef double CGFloat;
+ struct CGPoint {
+ CGFloat x;
+ CGFloat y;
+ };
+ typedef struct CGPoint CGPoint;
+ struct CGSize {
+ CGFloat width;
+ CGFloat height;
+ };
+ typedef struct CGSize CGSize;
+ struct CGRect {
+ CGPoint origin;
+ CGSize size;
+ };
+ typedef struct CGRect CGRect;
+
+ typedef CGPoint NSPoint;
+ typedef CGSize NSSize;
+ typedef CGRect NSRect;
+
+ typedef struct objc_class *Class;
+ typedef struct objc_object {
+ Class isa;
+ } *id;
+ typedef struct objc_selector *SEL;
+
+ SEL sel_registerName(const char *str);
+ id objc_getClass(const char *name);
+ id objc_msgSend(id theReceiver, SEL theSelector, ...);
+
+''')
+
+objc = ffi.dlopen('objc')
+appkit = ffi.dlopen('AppKit')
+
+nil = ffi.NULL
+YES = ffi.cast('BOOL', 1)
+NO = ffi.cast('BOOL', 0)
+
+NSASCIIStringEncoding = ffi.cast('NSStringEncoding', 1)
+NSApplicationActivationPolicyRegular = ffi.cast('NSApplicationActivationPolicy', 0)
+NSTitledWindowMask = ffi.cast('NSUInteger', 1)
+NSBackingStoreBuffered = ffi.cast('NSBackingStoreType', 2)
+
+NSMakePoint = lambda x, y: ffi.new('NSPoint *', (x, y))[0]
+NSMakeRect = lambda x, y, w, h: ffi.new('NSRect *', ((x, y), (w, h)))[0]
+
+get, send, sel = objc.objc_getClass, objc.objc_msgSend, objc.sel_registerName
+at = lambda s: send(
+ get('NSString'),
+ sel('stringWithCString:encoding:'),
+ ffi.new('char[]', s), NSASCIIStringEncoding)
+
+send(get('NSAutoreleasePool'), sel('new'))
+app = send(get('NSApplication'), sel('sharedApplication'))
+send(app, sel('setActivationPolicy:'), NSApplicationActivationPolicyRegular)
+
+menubar = send(send(get('NSMenu'), sel('new')), sel('autorelease'))
+appMenuItem = send(send(get('NSMenuItem'), sel('new')), sel('autorelease'))
+send(menubar, sel('addItem:'), appMenuItem)
+send(app, sel('setMainMenu:'), menubar)
+
+appMenu = send(send(get('NSMenu'), sel('new')), sel('autorelease'))
+appName = send(send(get('NSProcessInfo'), sel('processInfo')), sel('processName'))
+quitTitle = send(at('Quit '), sel('stringByAppendingString:'), appName)
+quitMenuItem = send(send(send(
+ get('NSMenuItem'), sel('alloc')),
+ sel('initWithTitle:action:keyEquivalent:'),
+ quitTitle, sel('terminate:'), at('q')),
+ sel('autorelease'))
+send(appMenu, sel('addItem:'), quitMenuItem)
+send(appMenuItem, sel('setSubmenu:'), appMenu)
+
+window = send(send(send(
+ get('NSWindow'), sel('alloc')),
+ sel('initWithContentRect:styleMask:backing:defer:'),
+ NSMakeRect(0, 0, 200, 200), NSTitledWindowMask, NSBackingStoreBuffered, NO),
+ sel('autorelease'))
+send(window, sel('cascadeTopLeftFromPoint:'), NSMakePoint(20, 20))
+send(window, sel('setTitle:'), appName)
+send(window, sel('makeKeyAndOrderFront:'), nil)
+
+send(app, sel('activateIgnoringOtherApps:'), YES)
+send(app, sel('run'))
diff --git a/demo/embedding.py b/demo/embedding.py
new file mode 100644
index 0000000..b15c050
--- /dev/null
+++ b/demo/embedding.py
@@ -0,0 +1,21 @@
+import cffi
+
+ffibuilder = cffi.FFI()
+
+ffibuilder.embedding_api("""
+ int add(int, int);
+""")
+
+ffibuilder.embedding_init_code("""
+ from _embedding_cffi import ffi
+ print("preparing") # printed once
+
+ @ffi.def_extern()
+ def add(x, y):
+ print("adding %d and %d" % (x, y))
+ return x + y
+""")
+
+ffibuilder.set_source("_embedding_cffi", "")
+
+ffibuilder.compile(verbose=True)
diff --git a/demo/embedding_test.c b/demo/embedding_test.c
new file mode 100644
index 0000000..ede8cb9
--- /dev/null
+++ b/demo/embedding_test.c
@@ -0,0 +1,43 @@
+/* There are two options:
+
+ =====1=====
+
+ Link this program with _embedding_test.so.
+ E.g. with gcc:
+
+ gcc -o embedding_test embedding_test.c _embedding_cffi*.so
+
+ You must then run the executable with the right command
+ (LD_LIBRARY_PATH on Linux), otherwise it won't find the
+ _embedding_cffi*.so:
+
+ LD_LIBRARY_PATH=. ./embedding_test
+
+ There are platform-specific options to gcc to avoid needing
+ that, too. Linux:
+
+ gcc -o embedding_test embedding_test.c _embedding_cffi*.so \
+ -Wl,-rpath=\$ORIGIN/
+
+ =====2=====
+
+ Compile and link the _embedding_test.c source code together with
+ this example (e.g. with PyPy):
+
+ gcc -o embedding_test embedding_test.c _embedding_cffi.c \
+ -I/opt/pypy/include -pthread -lpypy-c
+*/
+
+#include <stdio.h>
+
+extern int add(int x, int y);
+
+
+int main(void)
+{
+ int res = add(40, 2);
+ printf("result: %d\n", res);
+ res = add(100, -5);
+ printf("result: %d\n", res);
+ return 0;
+}
diff --git a/demo/extern_python.py b/demo/extern_python.py
new file mode 100644
index 0000000..f315cc5
--- /dev/null
+++ b/demo/extern_python.py
@@ -0,0 +1,26 @@
+import cffi
+
+ffi = cffi.FFI()
+
+ffi.cdef("""int my_algo(int); extern "Python" int f(int);""")
+
+ffi.set_source("_extern_python_cffi", """
+ static int f(int);
+ static int my_algo(int n) {
+ int i, sum = 0;
+ for (i = 0; i < n; i++)
+ sum += f(i);
+ return sum;
+ }
+""")
+
+ffi.compile()
+
+
+from _extern_python_cffi import ffi, lib
+
+@ffi.def_extern()
+def f(n):
+ return n * n
+
+assert lib.my_algo(10) == 0+1+4+9+16+25+36+49+64+81
diff --git a/demo/extern_python_varargs.py b/demo/extern_python_varargs.py
new file mode 100644
index 0000000..ee78079
--- /dev/null
+++ b/demo/extern_python_varargs.py
@@ -0,0 +1,61 @@
+import cffi
+
+ffi = cffi.FFI()
+
+ffi.cdef("""
+ int my_algo(int);
+ typedef ... va_list;
+ extern "Python" int f(int, va_list *);
+
+ int fetch_int(va_list *);
+ double fetch_double(va_list *);
+ void *fetch_ptr(va_list *);
+""")
+
+ffi.set_source("_extern_python_cffi", """
+ #include <stdarg.h>
+
+ static int f(int, va_list *);
+
+ static int f1(int n, ...)
+ {
+ va_list ap;
+ va_start(ap, n);
+ int res = f(n, &ap);
+ va_end(ap);
+ return res;
+ }
+
+ static int fetch_int(va_list *va) { return va_arg((*va), int); }
+ static double fetch_double(va_list *va) { return va_arg((*va), double); }
+ static void * fetch_ptr(va_list *va) { return va_arg((*va), void *); }
+
+ static int my_algo(int n) {
+ return f1(3, n, n+1, n+2) + f1(1, &n) + f1(2, 12.3, 45.6);
+ }
+""")
+
+ffi.compile()
+
+
+from _extern_python_cffi import ffi, lib
+
+@ffi.def_extern()
+def f(n, va):
+ if n == 3:
+ x = lib.fetch_int(va)
+ y = lib.fetch_int(va)
+ z = lib.fetch_int(va)
+ print (x, y, z)
+ elif n == 1:
+ ptr = lib.fetch_ptr(va)
+ print 'ptr to:', ffi.cast("int *", ptr)[0]
+ elif n == 2:
+ x = lib.fetch_double(va)
+ y = lib.fetch_double(va)
+ print (x, y)
+ else:
+ raise AssertionError(n)
+ return 14
+
+print lib.my_algo(10)
diff --git a/demo/fastcsv.py b/demo/fastcsv.py
new file mode 100644
index 0000000..6b8d0b4
--- /dev/null
+++ b/demo/fastcsv.py
@@ -0,0 +1,266 @@
+import csv
+import cffi
+
+# IN-PROGRESS. See the demo at the end of the file
+
+
+def _make_ffi_from_dialect(dialect_name):
+ dialect = csv.get_dialect(dialect_name)
+
+ ffi = cffi.FFI()
+
+ ffi.cdef("""
+ long parse_line(char *rawline, long inputlength);
+ """)
+
+ d = {'quotechar': ord(dialect.quotechar),
+ 'quoting': int(dialect.quoting),
+ 'skipinitialspace': int(dialect.skipinitialspace),
+ 'delimiter': ord(dialect.delimiter),
+ 'doublequote': int(dialect.doublequote),
+ 'strict': int(dialect.strict),
+ }
+ if dialect.escapechar is not None:
+ d['is_escape_char'] = '== %d' % ord(dialect.escapechar)
+ else:
+ d['is_escape_char'] = '&& 0'
+
+ ffi.set_source('_fastcsv_' + dialect_name, r'''
+
+ typedef enum {
+ START_RECORD, START_FIELD, ESCAPED_CHAR, IN_FIELD,
+ IN_QUOTED_FIELD, ESCAPE_IN_QUOTED_FIELD, QUOTE_IN_QUOTED_FIELD,
+ EAT_CRNL
+ } ParserState;
+
+ typedef enum {
+ QUOTE_MINIMAL, QUOTE_ALL, QUOTE_NONNUMERIC, QUOTE_NONE
+ } QuoteStyle;
+
+ typedef struct {
+ ParserState state; /* current CSV parse state */
+ char *field; /* build current field in here */
+ int field_size; /* size of allocated buffer */
+ int field_len; /* length of current field */
+ int numeric_field; /* treat field as numeric */
+ } ReaderObj;
+
+ static void
+ parse_add_char(ReaderObj *self, char c)
+ {
+ *self->field++ = c;
+ }
+
+ static void
+ parse_save_field(ReaderObj *self)
+ {
+ *self->field++ = 0;
+ }
+
+ static int
+ parse_process_char(ReaderObj *self, char c)
+ {
+ switch (self->state) {
+ case START_RECORD:
+ /* start of record */
+ if (c == '\0')
+ /* empty line - return [] */
+ break;
+ else if (c == '\n' || c == '\r') {
+ self->state = EAT_CRNL;
+ break;
+ }
+ /* normal character - handle as START_FIELD */
+ self->state = START_FIELD;
+ /* fallthru */
+ case START_FIELD:
+ /* expecting field */
+ if (c == '\n' || c == '\r' || c == '\0') {
+ /* save empty field - return [fields] */
+ parse_save_field(self);
+ self->state = (c == '\0' ? START_RECORD : EAT_CRNL);
+ }
+ else if (c == %(quotechar)d &&
+ %(quoting)d != QUOTE_NONE) {
+ /* start quoted field */
+ self->state = IN_QUOTED_FIELD;
+ }
+ else if (c %(is_escape_char)s) {
+ /* possible escaped character */
+ self->state = ESCAPED_CHAR;
+ }
+ else if (c == ' ' && %(skipinitialspace)d)
+ /* ignore space at start of field */
+ ;
+ else if (c == %(delimiter)d) {
+ /* save empty field */
+ parse_save_field(self);
+ }
+ else {
+ /* begin new unquoted field */
+ if (%(quoting)d == QUOTE_NONNUMERIC)
+ self->numeric_field = 1;
+ parse_add_char(self, c);
+ self->state = IN_FIELD;
+ }
+ break;
+
+ case ESCAPED_CHAR:
+ if (c == '\0')
+ c = '\n';
+ parse_add_char(self, c);
+ self->state = IN_FIELD;
+ break;
+
+ case IN_FIELD:
+ /* in unquoted field */
+ if (c == '\n' || c == '\r' || c == '\0') {
+ /* end of line - return [fields] */
+ parse_save_field(self);
+ self->state = (c == '\0' ? START_RECORD : EAT_CRNL);
+ }
+ else if (c %(is_escape_char)s) {
+ /* possible escaped character */
+ self->state = ESCAPED_CHAR;
+ }
+ else if (c == %(delimiter)d) {
+ /* save field - wait for new field */
+ parse_save_field(self);
+ self->state = START_FIELD;
+ }
+ else {
+ /* normal character - save in field */
+ parse_add_char(self, c);
+ }
+ break;
+
+ case IN_QUOTED_FIELD:
+ /* in quoted field */
+ if (c == '\0')
+ ;
+ else if (c %(is_escape_char)s) {
+ /* Possible escape character */
+ self->state = ESCAPE_IN_QUOTED_FIELD;
+ }
+ else if (c == %(quotechar)d &&
+ %(quoting)d != QUOTE_NONE) {
+ if (%(doublequote)d) {
+ /* doublequote; " represented by "" */
+ self->state = QUOTE_IN_QUOTED_FIELD;
+ }
+ else {
+ /* end of quote part of field */
+ self->state = IN_FIELD;
+ }
+ }
+ else {
+ /* normal character - save in field */
+ parse_add_char(self, c);
+ }
+ break;
+
+ case ESCAPE_IN_QUOTED_FIELD:
+ if (c == '\0')
+ c = '\n';
+ parse_add_char(self, c);
+ self->state = IN_QUOTED_FIELD;
+ break;
+
+ case QUOTE_IN_QUOTED_FIELD:
+ /* doublequote - seen a quote in an quoted field */
+ if (%(quoting)d != QUOTE_NONE &&
+ c == %(quotechar)d) {
+ /* save "" as " */
+ parse_add_char(self, c);
+ self->state = IN_QUOTED_FIELD;
+ }
+ else if (c == %(delimiter)d) {
+ /* save field - wait for new field */
+ parse_save_field(self);
+ self->state = START_FIELD;
+ }
+ else if (c == '\n' || c == '\r' || c == '\0') {
+ /* end of line - return [fields] */
+ parse_save_field(self);
+ self->state = (c == '\0' ? START_RECORD : EAT_CRNL);
+ }
+ else if (!%(strict)d) {
+ parse_add_char(self, c);
+ self->state = IN_FIELD;
+ }
+ else {
+ /* illegal */
+ /*PyErr_Format(error_obj, "'%%c' expected after '%%c'",
+ dialect->delimiter,
+ dialect->quotechar);*/
+ return -1;
+ }
+ break;
+
+ case EAT_CRNL:
+ if (c == '\n' || c == '\r')
+ ;
+ else if (c == '\0')
+ self->state = START_RECORD;
+ else {
+ /*PyErr_Format(error_obj, "new-line character seen in unquoted field - do you need to open the file in universal-newline mode?");*/
+ return -1;
+ }
+ break;
+
+ }
+ return 0;
+ }
+
+ static void
+ parse_reset(ReaderObj *self, char *rawline)
+ {
+ self->field = rawline;
+ self->state = START_RECORD;
+ self->numeric_field = 0;
+ }
+
+ long parse_line(char *rawline, long inputlength)
+ {
+ char *p;
+ ReaderObj reader;
+ parse_reset(&reader, rawline);
+
+ for (p=rawline; inputlength > 0; inputlength--, p++) {
+ if (parse_process_char(&reader, *p) < 0)
+ return -1;
+ }
+ if (parse_process_char(&reader, 0) < 0)
+ return -1;
+ return reader.field - rawline - 1;
+ }
+ ''' % d)
+
+ ffi.compile()
+
+
+def fastcsv_reader(f, dialect_name):
+ try:
+ module = __import__('_fastcsv_' + dialect_name)
+ except ImportError:
+ _make_ffi_from_dialect(dialect_name)
+ module = __import__('_fastcsv_' + dialect_name)
+ ffi, lib = module.ffi, module.lib
+ #
+ linelen = -1
+ for line in f:
+ if linelen <= len(line):
+ linelen = 2 * len(line)
+ rawline = ffi.new("char[]", linelen)
+ ffi.buffer(rawline, len(line))[:] = line
+ n = lib.parse_line(rawline, len(line))
+ assert n >= 0
+ yield ffi.buffer(rawline, n)[:].split('\x00')
+
+
+if __name__ == '__main__':
+ csv.register_dialect('unixpwd', delimiter=':', quoting=csv.QUOTE_NONE)
+ with open('/etc/passwd', 'rb') as f:
+ reader = fastcsv_reader(f, 'unixpwd')
+ for row in reader:
+ print row
diff --git a/demo/gmp.py b/demo/gmp.py
new file mode 100644
index 0000000..44f233c
--- /dev/null
+++ b/demo/gmp.py
@@ -0,0 +1,33 @@
+import sys
+#
+# This is only a demo based on the GMP library.
+# There is a rather more complete (but perhaps outdated) version available at:
+# http://bazaar.launchpad.net/~tolot-solar-empire/+junk/gmpy_cffi/files
+#
+
+try:
+ from _gmp_cffi import ffi, lib
+except ImportError:
+ print 'run gmp_build first, then make sure the shared object is on sys.path'
+ sys.exit(1)
+
+# ffi "knows" about the declared variables and functions from the
+# cdef parts of the module created from gmp_build
+# lib "knows" how to call the functions from the set_source parts
+# of the module.
+
+# ____________________________________________________________
+
+a = ffi.new("mpz_t")
+b = ffi.new("mpz_t")
+
+if len(sys.argv) < 3:
+ print 'call as %s bigint1, bigint2' % sys.argv[0]
+ sys.exit(2)
+
+lib.mpz_init_set_str(a, sys.argv[1], 10) # Assume decimal integers
+lib.mpz_init_set_str(b, sys.argv[2], 10) # Assume decimal integers
+lib.mpz_add(a, a, b) # a=a+b
+
+s = lib.mpz_get_str(ffi.NULL, 10, a)
+print ffi.string(s)
diff --git a/demo/gmp_build.py b/demo/gmp_build.py
new file mode 100644
index 0000000..e1a6000
--- /dev/null
+++ b/demo/gmp_build.py
@@ -0,0 +1,26 @@
+import cffi
+
+#
+# This is only a demo based on the GMP library.
+# There is a rather more complete (but perhaps outdated) version available at:
+# http://bazaar.launchpad.net/~tolot-solar-empire/+junk/gmpy_cffi/files
+#
+
+ffibuilder = cffi.FFI()
+
+ffibuilder.cdef("""
+
+ typedef struct { ...; } MP_INT;
+ typedef MP_INT mpz_t[1];
+
+ int mpz_init_set_str (MP_INT *dest_integer, char *src_cstring, int base);
+ void mpz_add (MP_INT *sum, MP_INT *addend1, MP_INT *addend2);
+ char * mpz_get_str (char *string, int base, MP_INT *integer);
+
+""")
+
+ffibuilder.set_source('_gmp_cffi', "#include <gmp.h>",
+ libraries=['gmp', 'm'])
+
+if __name__ == '__main__':
+ ffibuilder.compile(verbose=True)
diff --git a/demo/manual.c b/demo/manual.c
new file mode 100644
index 0000000..5b360e8
--- /dev/null
+++ b/demo/manual.c
@@ -0,0 +1,166 @@
+#include "_cffi_include.h"
+
+
+#define AA (42)
+#define BB (&bb)
+static int bb = 16261;
+
+int foo42(int a, int *b)
+{
+ return a - *b;
+}
+
+int foo64(int a)
+{
+ return ~a;
+}
+
+struct foo_s {
+ int a;
+};
+
+/************************************************************/
+
+static void *_cffi_types[] = {
+ _CFFI_OP(_CFFI_OP_FUNCTION, 1),
+ _CFFI_OP(_CFFI_OP_PRIMITIVE, _CFFI_PRIM_INT),
+ _CFFI_OP(_CFFI_OP_POINTER, 1),
+ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0),
+ _CFFI_OP(_CFFI_OP_FUNCTION, 1),
+ _CFFI_OP(_CFFI_OP_PRIMITIVE, _CFFI_PRIM_INT),
+ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0),
+ _CFFI_OP(_CFFI_OP_STRUCT_UNION, 0),
+};
+
+#ifndef PYPY_VERSION
+static PyObject *
+_cffi_f_foo42(PyObject *self, PyObject *args)
+{
+ int x0;
+ int * x1;
+ Py_ssize_t datasize;
+ int result;
+ PyObject *arg0;
+ PyObject *arg1;
+
+ if (!PyArg_ParseTuple(args, "OO:foo42", &arg0, &arg1))
+ return NULL;
+
+ x0 = _cffi_to_c_int(arg0, int);
+ if (x0 == (int)-1 && PyErr_Occurred())
+ return NULL;
+
+ datasize = _cffi_prepare_pointer_call_argument(
+ _cffi_types[1], arg1, (char **)&x1);
+ if (datasize != 0) {
+ if (datasize < 0)
+ return NULL;
+ x1 = alloca(datasize);
+ memset((void *)x1, 0, datasize);
+ if (_cffi_convert_array_from_object((char *)x1, _cffi_types[1], arg1) < 0)
+ return NULL;
+ }
+
+ Py_BEGIN_ALLOW_THREADS
+ _cffi_restore_errno();
+ { result = foo42(x0, x1); }
+ _cffi_save_errno();
+ Py_END_ALLOW_THREADS
+
+ return _cffi_from_c_int(result, int);
+}
+#else
+static int _cffi_f_foo42(int x0, int *x1)
+{
+ return foo42(x0, x1);
+}
+#endif
+
+#ifndef PYPY_VERSION
+static PyObject *
+_cffi_f_foo64(PyObject *self, PyObject *arg0)
+{
+ int x0;
+ int result;
+
+ x0 = _cffi_to_c_int(arg0, int);
+ if (x0 == (int)-1 && PyErr_Occurred())
+ return NULL;
+
+ Py_BEGIN_ALLOW_THREADS
+ _cffi_restore_errno();
+ { result = foo64(x0); }
+ _cffi_save_errno();
+ Py_END_ALLOW_THREADS
+
+ return _cffi_from_c_int(result, int);
+}
+#else
+static int _cffi_f_foo64(int x0)
+{
+ return foo64(x0);
+}
+#endif
+
+static int _cffi_const_AA(unsigned long long *output)
+{
+ *output = (unsigned long long)((AA) << 0); // integer
+ return (AA) <= 0;
+}
+
+static void _cffi_const_BB(char *output)
+{
+ *(int **)output = BB;
+}
+
+static const struct _cffi_global_s _cffi_globals[] = {
+ { "AA", &_cffi_const_AA, _CFFI_OP(_CFFI_OP_CONSTANT_INT, 0) },
+ { "BB", &_cffi_const_BB, _CFFI_OP(_CFFI_OP_CONSTANT, 2) },
+ { "bb", &bb, _CFFI_OP(_CFFI_OP_GLOBAL_VAR, 1) },
+ { "foo42", &_cffi_f_foo42, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 0) },
+ { "foo64", &_cffi_f_foo64, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 4) },
+};
+
+struct _cffi_align_foo_s { char x; struct foo_s y; };
+
+static const struct _cffi_struct_union_s _cffi_struct_unions[] = {
+ { "foo_s", 7, 0,
+ sizeof(struct foo_s),
+ offsetof(struct _cffi_align_foo_s, y),
+ 1, 0 },
+};
+
+static const struct _cffi_field_s _cffi_fields[] = {
+ { "a", offsetof(struct foo_s, a), sizeof(((struct foo_s *)0)->a),
+ _CFFI_OP(_CFFI_OP_NOOP, 1) },
+};
+
+static const struct _cffi_type_context_s _cffi_type_context = {
+ _cffi_types,
+ _cffi_globals,
+ _cffi_fields,
+ _cffi_struct_unions,
+ NULL,
+ NULL,
+ 5, /* num_globals */
+ 1, /* num_struct_unions */
+ 0,
+ 0,
+ NULL,
+ 8, /* num_types */
+};
+
+#ifndef PYPY_VERSION
+PyMODINIT_FUNC
+initmanual(void)
+{
+ _cffi_init("manual", 0x2601, &_cffi_type_context);
+}
+#else
+PyMODINIT_FUNC
+_cffi_pypyinit_manual(const void *p[])
+{
+ p[0] = (const void *)0x2601;
+ p[1] = &_cffi_type_context;
+}
+#endif
diff --git a/demo/manual2.py b/demo/manual2.py
new file mode 100644
index 0000000..2986244
--- /dev/null
+++ b/demo/manual2.py
@@ -0,0 +1,34 @@
+import _cffi_backend
+
+ffi = _cffi_backend.FFI(b"manual2",
+ _version = 0x2601,
+ _types = b'\x00\x00\x01\x0D\x00\x00\x07\x01\x00\x00\x00\x0F\x00\x00\x00\x09\x00\x00\x00\x0B\x00\x00\x01\x03',
+ _globals = (b'\xff\xff\xff\x0bAA',0,b'\xff\xff\xff\x0bBB',-1,b'\xff\xff\xff\x0bCC',2,b'\xff\xff\xff\x1fFOO',0x9999999999999999,b'\x00\x00\x00#close',0,b'\x00\x00\x05#stdout',0),
+ _struct_unions = ((b'\x00\x00\x00\x03\x00\x00\x00\x00point_s',b'\x00\x00\x01\x11\xff\xff\xff\xffx',b'\x00\x00\x01\x11\xff\xff\xff\xffy'),),
+ _enums = (b'\x00\x00\x00\x04\x00\x00\x00\x07myenum_e\x00AA,BB,CC',),
+ _typenames = (b'\x00\x00\x00\x01myint_t',),
+)
+
+
+
+# trying it out
+lib = ffi.dlopen(None)
+assert lib.AA == 0
+assert lib.BB == -1
+assert lib.FOO == 0x9999999999999999
+x = lib.close(-42)
+assert x == -1
+
+print lib.stdout
+
+print ffi.new("struct point_s *")
+print ffi.offsetof("struct point_s", "x")
+print ffi.offsetof("struct point_s", "y")
+print ffi.new("struct point_s[CC]")
+assert ffi.sizeof("struct point_s[CC]") == 2 * ffi.sizeof("struct point_s")
+
+print ffi.cast("enum myenum_e", 2)
+print ffi.cast("myint_t", -2)
+assert ffi.typeof("myint_t") == ffi.typeof("int")
+
+del ffi, lib
diff --git a/demo/pwuid.py b/demo/pwuid.py
new file mode 100644
index 0000000..dda9299
--- /dev/null
+++ b/demo/pwuid.py
@@ -0,0 +1,7 @@
+import sys, os
+
+# run pwuid_build first, then make sure the shared object is on sys.path
+from _pwuid_cffi import ffi, lib
+
+
+print ffi.string(lib.getpwuid(0).pw_name)
diff --git a/demo/pwuid_build.py b/demo/pwuid_build.py
new file mode 100644
index 0000000..7ef0d76
--- /dev/null
+++ b/demo/pwuid_build.py
@@ -0,0 +1,18 @@
+from cffi import FFI
+ffi = FFI()
+ffi.cdef(""" // some declarations from the man page
+ struct passwd {
+ char *pw_name;
+ ...;
+ };
+ struct passwd *getpwuid(int uid);
+""")
+
+ffi.set_source('_pwuid_cffi', """ // passed to the real C compiler
+#include <sys/types.h>
+#include <pwd.h>
+""")
+
+
+if __name__ == '__main__':
+ ffi.compile()
diff --git a/demo/py.cleanup b/demo/py.cleanup
new file mode 100755
index 0000000..512389f
--- /dev/null
+++ b/demo/py.cleanup
@@ -0,0 +1,31 @@
+#! /usr/bin/env python
+import sys, os, stat
+from bsdopendirtype import opendir
+
+def clean(path):
+ global count
+ try:
+ content = opendir(path)
+ except OSError:
+ print >> sys.stderr, "skipping", path
+ return
+ for filename, smode in content:
+ if stat.S_ISDIR(smode):
+ clean(filename)
+ if filename.endswith('/__pycache__'):
+ try:
+ os.rmdir(filename)
+ except OSError:
+ pass
+ elif (filename.endswith('.pyc') or filename.endswith('.pyo') or
+ filename.endswith('.pyc~') or filename.endswith('.pyo~')):
+ os.unlink(filename)
+ count += 1
+
+count = 0
+
+for arg in sys.argv[1:] or ['.']:
+ print "cleaning path", arg, "of .pyc/.pyo/__pycache__ files"
+ clean(arg)
+
+print "%d files removed" % (count,)
diff --git a/demo/pyobj.py b/demo/pyobj.py
new file mode 100644
index 0000000..b40343a
--- /dev/null
+++ b/demo/pyobj.py
@@ -0,0 +1,124 @@
+
+referents = [] # list "object descriptor -> python object"
+freelist = None
+
+def store(x):
+ "Store the object 'x' and returns a new object descriptor for it."
+ global freelist
+ p = freelist
+ if p is None:
+ p = len(referents)
+ referents.append(x)
+ else:
+ freelist = referents[p]
+ referents[p] = x
+ return p
+
+def discard(p):
+ """Discard (i.e. close) the object descriptor 'p'.
+ Return the original object that was attached to 'p'."""
+ global freelist
+ x = referents[p]
+ referents[p] = freelist
+ freelist = p
+ return x
+
+class Ref(object):
+ """For use in 'with Ref(x) as ob': open an object descriptor
+ and returns it in 'ob', and close it automatically when the
+ 'with' statement finishes."""
+ def __init__(self, x):
+ self.x = x
+ def __enter__(self):
+ self.p = p = store(self.x)
+ return p
+ def __exit__(self, *args):
+ discard(self.p)
+
+def count_pyobj_alive():
+ result = len(referents)
+ p = freelist
+ while p is not None:
+ assert result > 0
+ result -= 1
+ p = referents[p]
+ return result
+
+# ------------------------------------------------------------
+
+if __name__ == '__main__':
+ import api
+
+ ffi = api.PythonFFI()
+
+ ffi.cdef("""
+ typedef int pyobj_t;
+ int sum_integers(pyobj_t p_list);
+ pyobj_t sum_objects(pyobj_t p_list, pyobj_t p_initial);
+ """)
+
+ @ffi.pyexport("int(pyobj_t)")
+ def length(p_list):
+ list = referents[p_list]
+ return len(list)
+
+ @ffi.pyexport("int(pyobj_t, int)")
+ def getitem(p_list, index):
+ list = referents[p_list]
+ return list[index]
+
+ @ffi.pyexport("pyobj_t(pyobj_t)")
+ def pyobj_dup(p):
+ return store(referents[p])
+
+ @ffi.pyexport("void(pyobj_t)")
+ def pyobj_close(p):
+ discard(p)
+
+ @ffi.pyexport("pyobj_t(pyobj_t, int)")
+ def pyobj_getitem(p_list, index):
+ list = referents[p_list]
+ return store(list[index])
+
+ @ffi.pyexport("pyobj_t(pyobj_t, pyobj_t)")
+ def pyobj_add(p1, p2):
+ return store(referents[p1] + referents[p2])
+
+ lib = ffi.verify("""
+ typedef int pyobj_t; /* an "object descriptor" number */
+
+ int sum_integers(pyobj_t p_list) {
+ /* this a demo function written in C, using the API
+ defined above: length() and getitem(). */
+ int i, result = 0;
+ int count = length(p_list);
+ for (i=0; i<count; i++) {
+ int n = getitem(p_list, i);
+ result += n;
+ }
+ return result;
+ }
+
+ pyobj_t sum_objects(pyobj_t p_list, pyobj_t p_initial) {
+ /* same as above, but keeps all additions as Python objects */
+ int i;
+ int count = length(p_list);
+ pyobj_t p1 = pyobj_dup(p_initial);
+ for (i=0; i<count; i++) {
+ pyobj_t p2 = pyobj_getitem(p_list, i);
+ pyobj_t p3 = pyobj_add(p1, p2);
+ pyobj_close(p2);
+ pyobj_close(p1);
+ p1 = p3;
+ }
+ return p1;
+ }
+ """)
+
+ with Ref([10, 20, 30, 40]) as p_list:
+ print lib.sum_integers(p_list)
+ with Ref(5) as p_initial:
+ result = discard(lib.sum_objects(p_list, p_initial))
+ print result
+
+ assert count_pyobj_alive() == 0
diff --git a/demo/readdir.py b/demo/readdir.py
new file mode 100644
index 0000000..b966246
--- /dev/null
+++ b/demo/readdir.py
@@ -0,0 +1,35 @@
+# A Linux-only demo
+#
+import sys
+
+if not sys.platform.startswith('linux'):
+ raise Exception("Linux-only demo")
+
+from _readdir import ffi
+lib = ffi.dlopen(None)
+
+
+def walk(basefd, path):
+ print '{', path
+ dirfd = lib.openat(basefd, path, 0)
+ if dirfd < 0:
+ # error in openat()
+ return
+ dir = lib.fdopendir(dirfd)
+ dirent = ffi.new("struct dirent *")
+ result = ffi.new("struct dirent **")
+ while True:
+ if lib.readdir_r(dir, dirent, result):
+ # error in readdir_r()
+ break
+ if result[0] == ffi.NULL:
+ break
+ name = ffi.string(dirent.d_name)
+ print '%3d %s' % (dirent.d_type, name)
+ if dirent.d_type == 4 and name != '.' and name != '..':
+ walk(dirfd, name)
+ lib.closedir(dir)
+ print '}'
+
+
+walk(-1, "/tmp")
diff --git a/demo/readdir2.py b/demo/readdir2.py
new file mode 100644
index 0000000..b564b51
--- /dev/null
+++ b/demo/readdir2.py
@@ -0,0 +1,35 @@
+# A Linux-only demo, using set_source() instead of hard-coding the exact layouts
+#
+import sys
+
+if not sys.platform.startswith('linux'):
+ raise Exception("Linux-only demo")
+
+# run readdir2_build first, then make sure the shared object is on sys.path
+from _readdir2_cffi import ffi, lib
+
+
+def walk(basefd, path):
+ print '{', path
+ dirfd = lib.openat(basefd, path, 0)
+ if dirfd < 0:
+ # error in openat()
+ return
+ dir = lib.fdopendir(dirfd)
+ dirent = ffi.new("struct dirent *")
+ result = ffi.new("struct dirent **")
+ while True:
+ if lib.readdir_r(dir, dirent, result):
+ # error in readdir_r()
+ break
+ if result[0] == ffi.NULL:
+ break
+ name = ffi.string(dirent.d_name)
+ print '%3d %s' % (dirent.d_type, name)
+ if dirent.d_type == lib.DT_DIR and name != '.' and name != '..':
+ walk(dirfd, name)
+ lib.closedir(dir)
+ print '}'
+
+
+walk(-1, "/tmp")
diff --git a/demo/readdir2_build.py b/demo/readdir2_build.py
new file mode 100644
index 0000000..5cfd872
--- /dev/null
+++ b/demo/readdir2_build.py
@@ -0,0 +1,36 @@
+from cffi import FFI
+
+ffi = FFI()
+ffi.cdef("""
+
+ typedef ... DIR;
+
+ struct dirent {
+ unsigned char d_type; /* type of file; not supported
+ by all file system types */
+ char d_name[...]; /* filename */
+ ...;
+ };
+
+ int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result);
+ int openat(int dirfd, const char *pathname, int flags);
+ DIR *fdopendir(int fd);
+ int closedir(DIR *dirp);
+
+ static const int DT_DIR;
+
+""")
+ffi.set_source("_readdir2_cffi", """
+#ifndef _ATFILE_SOURCE
+# define _ATFILE_SOURCE
+#endif
+#ifndef _BSD_SOURCE
+# define _BSD_SOURCE
+#endif
+#include <fcntl.h>
+#include <sys/types.h>
+#include <dirent.h>
+""")
+
+if __name__ == '__main__':
+ ffi.compile()
diff --git a/demo/readdir2_setup.py b/demo/readdir2_setup.py
new file mode 100644
index 0000000..bd8c19f
--- /dev/null
+++ b/demo/readdir2_setup.py
@@ -0,0 +1,9 @@
+from distutils.core import setup
+import readdir2_build
+
+setup(
+ name="readdir2",
+ version="0.1",
+ py_modules=["readdir2"],
+ ext_modules=[readdir2_build.ffi.distutils_extension('build')],
+)
diff --git a/demo/readdir_build.py b/demo/readdir_build.py
new file mode 100644
index 0000000..f97f404
--- /dev/null
+++ b/demo/readdir_build.py
@@ -0,0 +1,33 @@
+import sys
+from cffi import FFI
+
+if not sys.platform.startswith('linux'):
+ raise Exception("Linux-only demo")
+
+
+ffi = FFI()
+ffi.cdef("""
+
+ typedef void DIR;
+ typedef long ino_t;
+ typedef long off_t;
+
+ struct dirent {
+ ino_t d_ino; /* inode number */
+ off_t d_off; /* offset to the next dirent */
+ unsigned short d_reclen; /* length of this record */
+ unsigned char d_type; /* type of file; not supported
+ by all file system types */
+ char d_name[256]; /* filename */
+ };
+
+ int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result);
+ int openat(int dirfd, const char *pathname, int flags);
+ DIR *fdopendir(int fd);
+ int closedir(DIR *dirp);
+
+""")
+ffi.set_source("_readdir", None)
+
+if __name__ == '__main__':
+ ffi.compile()
diff --git a/demo/readdir_ctypes.py b/demo/readdir_ctypes.py
new file mode 100644
index 0000000..4fd1d17
--- /dev/null
+++ b/demo/readdir_ctypes.py
@@ -0,0 +1,69 @@
+# A Linux-only demo
+#
+# For comparison purposes, this is a ctypes version of readdir.py.
+import sys
+import ctypes
+
+if not sys.platform.startswith('linux'):
+ raise Exception("Linux-only demo")
+
+
+DIR_p = ctypes.c_void_p
+ino_t = ctypes.c_long
+off_t = ctypes.c_long
+
+class DIRENT(ctypes.Structure):
+ _fields_ = [
+ ('d_ino', ino_t), # inode number
+ ('d_off', off_t), # offset to the next dirent
+ ('d_reclen', ctypes.c_ushort), # length of this record
+ ('d_type', ctypes.c_ubyte), # type of file; not supported
+ # by all file system types
+ ('d_name', ctypes.c_char * 256), # filename
+ ]
+DIRENT_p = ctypes.POINTER(DIRENT)
+DIRENT_pp = ctypes.POINTER(DIRENT_p)
+
+C = ctypes.CDLL(None)
+
+readdir_r = C.readdir_r
+readdir_r.argtypes = [DIR_p, DIRENT_p, DIRENT_pp]
+readdir_r.restype = ctypes.c_int
+
+openat = C.openat
+openat.argtypes = [ctypes.c_int, ctypes.c_char_p, ctypes.c_int]
+openat.restype = ctypes.c_int
+
+fdopendir = C.fdopendir
+fdopendir.argtypes = [ctypes.c_int]
+fdopendir.restype = DIR_p
+
+closedir = C.closedir
+closedir.argtypes = [DIR_p]
+closedir.restype = ctypes.c_int
+
+
+def walk(basefd, path):
+ print '{', path
+ dirfd = openat(basefd, path, 0)
+ if dirfd < 0:
+ # error in openat()
+ return
+ dir = fdopendir(dirfd)
+ dirent = DIRENT()
+ result = DIRENT_p()
+ while True:
+ if readdir_r(dir, dirent, result):
+ # error in readdir_r()
+ break
+ if not result:
+ break
+ name = dirent.d_name
+ print '%3d %s' % (dirent.d_type, name)
+ if dirent.d_type == 4 and name != '.' and name != '..':
+ walk(dirfd, name)
+ closedir(dir)
+ print '}'
+
+
+walk(-1, "/tmp")
diff --git a/demo/readdir_setup.py b/demo/readdir_setup.py
new file mode 100644
index 0000000..c8abdcb
--- /dev/null
+++ b/demo/readdir_setup.py
@@ -0,0 +1,11 @@
+from setuptools import setup
+
+setup(
+ name="example",
+ version="0.1",
+ py_modules=["readdir"],
+ setup_requires=["cffi>=1.0.dev0"],
+ cffi_modules=["readdir_build.py:ffi"],
+ install_requires=["cffi>=1.0.dev0"],
+ zip_safe=False,
+)
diff --git a/demo/recopendirtype.py b/demo/recopendirtype.py
new file mode 100644
index 0000000..768318b
--- /dev/null
+++ b/demo/recopendirtype.py
@@ -0,0 +1,50 @@
+from _recopendirtype import ffi, lib
+
+
+def _posix_error():
+ raise OSError(ffi.errno, os.strerror(ffi.errno))
+
+_dtype_to_smode = {
+ lib.DT_BLK: 0o060000,
+ lib.DT_CHR: 0o020000,
+ lib.DT_DIR: 0o040000,
+ lib.DT_FIFO: 0o010000,
+ lib.DT_LNK: 0o120000,
+ lib.DT_REG: 0o100000,
+ lib.DT_SOCK: 0o140000,
+}
+
+def opendir(dir):
+ if len(dir) == 0:
+ dir = b'.'
+ dirname = dir
+ if not dirname.endswith(b'/'):
+ dirname += b'/'
+ dirp = lib.opendir(dir)
+ if dirp == ffi.NULL:
+ raise _posix_error()
+ dirent = ffi.new("struct dirent *")
+ result = ffi.new("struct dirent **")
+ try:
+ while True:
+ ffi.errno = 0
+ err = lib.readdir_r(dirp, dirent, result)
+ if err: # really got an error
+ raise OSError(err, os.strerror(err))
+ if result[0] == ffi.NULL:
+ return #
+ name = ffi.string(dirent.d_name)
+ if name == b'.' or name == b'..':
+ continue
+ name = dirname + name
+ try:
+ smode = _dtype_to_smode[dirent.d_type]
+ except KeyError:
+ smode = os.lstat(name).st_mode
+ yield name, smode
+ finally:
+ lib.closedir(dirp)
+
+if __name__ == '__main__':
+ for name, smode in opendir(b'/tmp'):
+ print(hex(smode), name)
diff --git a/demo/recopendirtype_build.py b/demo/recopendirtype_build.py
new file mode 100644
index 0000000..fa62a05
--- /dev/null
+++ b/demo/recopendirtype_build.py
@@ -0,0 +1,19 @@
+from cffi import FFI
+import bsdopendirtype_build
+
+ffi = FFI()
+
+# ========== This is a demo of ffi.include() ==========
+ffi.include(bsdopendirtype_build.ffi)
+
+ffi.cdef("""
+ int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result);
+""")
+
+ffi.set_source("_recopendirtype", """
+ #include <sys/types.h>
+ #include <dirent.h>
+""")
+
+if __name__ == '__main__':
+ ffi.compile()
diff --git a/demo/setup_manual.py b/demo/setup_manual.py
new file mode 100644
index 0000000..2569bb4
--- /dev/null
+++ b/demo/setup_manual.py
@@ -0,0 +1,5 @@
+from distutils.core import setup
+from distutils.extension import Extension
+setup(name='manual',
+ ext_modules=[Extension(name='manual',
+ sources=['manual.c'])])
diff --git a/demo/winclipboard.py b/demo/winclipboard.py
new file mode 100644
index 0000000..5278cd0
--- /dev/null
+++ b/demo/winclipboard.py
@@ -0,0 +1,40 @@
+__author__ = "Israel Fruchter <israel.fruchter@gmail.com>"
+
+import sys, os
+
+if not sys.platform == 'win32':
+ raise Exception("Windows-only demo")
+
+try:
+ from _winclipboard_cffi import ffi, lib
+except ImportError:
+ print 'run winclipboard_build first, then make sure the shared object is on sys.path'
+ sys.exit(1)
+
+# ffi "knows" about the declared variables and functions from the
+# cdef parts of the module _winclipboard_cffi created,
+# lib "knows" how to call the functions from the set_source parts
+# of the module.
+
+def CopyToClipboard(string):
+ '''
+ use win32 api to copy `string` to the clipboard
+ '''
+ hWnd = lib.GetConsoleWindow()
+
+ if lib.OpenClipboard(hWnd):
+ cstring = ffi.new("char[]", string)
+ size = ffi.sizeof(cstring)
+
+ # make it a moveable memory for other processes
+ hGlobal = lib.GlobalAlloc(lib.GMEM_MOVEABLE, size)
+ buffer = lib.GlobalLock(hGlobal)
+ lib.memcpy(buffer, cstring, size)
+ lib.GlobalUnlock(hGlobal)
+
+ res = lib.EmptyClipboard()
+ res = lib.SetClipboardData(lib.CF_TEXT, buffer)
+
+ lib.CloseClipboard()
+
+CopyToClipboard("hello world from cffi")
diff --git a/demo/winclipboard_build.py b/demo/winclipboard_build.py
new file mode 100644
index 0000000..1a510eb
--- /dev/null
+++ b/demo/winclipboard_build.py
@@ -0,0 +1,36 @@
+from cffi import FFI
+
+ffi = FFI()
+ffi.cdef('''
+ typedef void * HANDLE;
+ typedef HANDLE HWND;
+ typedef int BOOL;
+ typedef unsigned int UINT;
+ typedef int SIZE_T;
+ typedef char * LPTSTR;
+ typedef HANDLE HGLOBAL;
+ typedef HANDLE LPVOID;
+
+ HWND GetConsoleWindow(void);
+
+ LPVOID GlobalLock( HGLOBAL hMem );
+ BOOL GlobalUnlock( HGLOBAL hMem );
+ HGLOBAL GlobalAlloc(UINT uFlags, SIZE_T dwBytes);
+
+ BOOL OpenClipboard(HWND hWndNewOwner);
+ BOOL CloseClipboard(void);
+ BOOL EmptyClipboard(void);
+ HANDLE SetClipboardData(UINT uFormat, HANDLE hMem);
+
+ #define CF_TEXT ...
+ #define GMEM_MOVEABLE ...
+
+ void * memcpy(void * s1, void * s2, int n);
+ ''')
+
+ffi.set_source('_winclipboard_cffi', '''
+ #include <windows.h>
+''', libraries=["user32"])
+
+if __name__ == '__main__':
+ ffi.compile()
diff --git a/demo/xclient.py b/demo/xclient.py
new file mode 100644
index 0000000..e4b3dd2
--- /dev/null
+++ b/demo/xclient.py
@@ -0,0 +1,27 @@
+import sys, os
+
+# run xclient_build first, then make sure the shared object is on sys.path
+from _xclient_cffi import ffi, lib
+
+
+# ffi "knows" about the declared variables and functions from the
+# cdef parts of the module xclient_build created,
+# lib "knows" how to call the functions from the set_source parts
+# of the module.
+
+
+class XError(Exception):
+ pass
+
+def main():
+ display = lib.XOpenDisplay(ffi.NULL)
+ if display == ffi.NULL:
+ raise XError("cannot open display")
+ w = lib.XCreateSimpleWindow(display, lib.DefaultRootWindow(display),
+ 10, 10, 500, 350, 0, 0, 0)
+ lib.XMapRaised(display, w)
+ event = ffi.new("XEvent *")
+ lib.XNextEvent(display, event)
+
+if __name__ == '__main__':
+ main()
diff --git a/demo/xclient_build.py b/demo/xclient_build.py
new file mode 100644
index 0000000..d6ce9da
--- /dev/null
+++ b/demo/xclient_build.py
@@ -0,0 +1,25 @@
+from cffi import FFI
+ffi = FFI()
+ffi.cdef("""
+
+typedef ... Display;
+typedef struct { ...; } Window;
+
+typedef struct { int type; ...; } XEvent;
+
+Display *XOpenDisplay(char *display_name);
+Window DefaultRootWindow(Display *display);
+int XMapRaised(Display *display, Window w);
+Window XCreateSimpleWindow(Display *display, Window parent, int x, int y,
+ unsigned int width, unsigned int height,
+ unsigned int border_width, unsigned long border,
+ unsigned long background);
+int XNextEvent(Display *display, XEvent *event_return);
+""")
+
+ffi.set_source('_xclient_cffi', """
+ #include <X11/Xlib.h>
+""", libraries=['X11'])
+
+if __name__ == '__main__':
+ ffi.compile(verbose=True)