Skip to content

Instantly share code, notes, and snippets.

@micklat
Created February 9, 2014 22:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save micklat/8906673 to your computer and use it in GitHub Desktop.
Save micklat/8906673 to your computer and use it in GitHub Desktop.
mostly-isolated issue 888
import python except expr
type
# A non-borrowed (counted) reference. Avoid copying these around! Nimrod doesn't have
# the equivalent of an assignment constructor (yet?), so any copy of PyRef must be counted (use dup for that).
PyRef = object {.inheritable, byref.}
p: PPyObject
PPyRef* = ref PyRef
EPyException = object of E_Base
# forward declarations
proc getattr*(o: PPyRef, name: cstring) : PPyRef
proc handle_error(s : string) =
PyErr_Print()
raise newException(EPyException, s)
proc check(p: PPyObject) : PPyObject =
if p == nil: handle_error("check(nil)")
result = p
proc check(x: int) : int =
if x == -1: handle_error("check(-1)")
result = x
converter to_PPyRef*(p: PPyObject) : PPyRef =
new result
result.p = check(p)
proc new_list*(size: int): PPyRef = PyList_New(size)
proc new_tuple*(size: int): PPyRef = PyTuple_New(size)
converter to_py*(i: int) : PPyRef = PyInt_FromLong(int32(i))
proc to_py*(s: cstring) : PPyRef = PyString_fromString(s)
proc to_tuple*(vals: openarray[PPyRef]): PPyRef =
result = new_tuple(len(vals))
for i in 0..len(vals)-1:
let p = vals[i].p
discard check(PyTuple_SetItem(result.p, i, p))
Py_INCREF(p) # PyTuple_SetItem steals refs, I don't want that
proc `()`*(f: PPyRef, args: varargs[PPyRef]): PPyRef {.discardable.} =
let args_tup = to_tuple(args)
PyObject_CallObject(f.p, args_tup.p)
proc destroy(o: var PyRef) {.destructor.} =
if o.p != nil:
echo "decrefing"
Py_DECREF(o.p)
o.p = nil
proc getattr*(o: PPyRef, name: cstring) : PPyRef =
result = to_PPyRef(PyObject_GetAttrString(o.p, name))
proc py_import*(name : cstring) : PPyRef =
PyImport_ImportModule(name)
type
Interpreter = object {.bycopy.}
proc make_interpreter() : Interpreter =
Py_Initialize()
result = Interpreter()
proc destroy(interpreter : Interpreter) {.destructor.} =
Py_Finalize()
var py_interpreter = make_interpreter()
let n = 100
let lx = new_list(0)
for i in 1..n:
# compilation succeeds:
getattr(lx, "append")(to_py(1))
# compilation fails:
getattr(lx, "append")(1)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment