static int LuaObject_setattr(PyObject *obj, PyObject *attr, PyObject *value) { int ret = -1; int rc; lua_rawgeti(L, LUA_REGISTRYINDEX, ((LuaObject*)obj)->ref); if (lua_isnil(L, -1)) { lua_pop(L, 1); PyErr_SetString(PyExc_RuntimeError, "lost reference"); return -1; } if (!lua_istable(L, -1)) { lua_pop(L, -1); PyErr_SetString(PyExc_TypeError, "Lua object is not a table"); return -1; } rc = py_convert(L, attr, 0); if (rc) { rc = py_convert(L, value, 0); if (rc) { lua_settable(L, -3); ret = 0; } else { PyErr_SetString(PyExc_ValueError, "can't convert value"); } } else { PyErr_SetString(PyExc_ValueError, "can't convert key/attr"); } lua_settop(L, 0); return ret; }
static int _p_object_index_get(lua_State *L, py_object *obj, int keyn) { PyObject *key = LuaConvert(L, keyn); PyObject *item; int ret = 0; if (!key) { luaL_argerror(L, 1, "failed to convert key"); return 0; } item = PyObject_GetItem(obj->o, key); Py_DECREF(key); if (item) { ret = py_convert(L, item, 0); Py_DECREF(item); } else { PyErr_Clear(); if (lua_gettop(L) > keyn) { lua_pushvalue(L, keyn+1); ret = 1; } } return ret; }
static void py_object_call(lua_State *L) { py_object *pobj = get_py_object(L, lua_getparam(L, 1)); if (!PyCallable_Check(pobj->object)) { const char *name = pobj->object->ob_type->tp_name; char *format = "object \"%s\" is not callable"; const char *str = name ? name : "?"; char buff[buffsize_calc(2, format, str)]; sprintf(buff, format, str); lua_new_error(L, &buff[0]); } PyObject *args = NULL; PyObject *kwargs = NULL; PyObject *value; int nargs = lua_gettop(L)-1; lua_Object largs = lua_getparam(L, 2); lua_Object lkwargs = lua_getparam(L, nargs > 1 ? 3 : 2); bool isargs = ispyargs(L, largs), iskwargs = ispykwargs(L, lkwargs); if (nargs == 1 && (isargs || iskwargs)) { PyObject *obj = get_pobject(L, largs); if (PyTuple_Check(obj)) { args = obj; } else if (PyDict_Check(obj)) { args = PyTuple_New(0); if (!args) lua_new_error(L, "#1 failed to create arguments tuple"); kwargs = obj; } else { lua_error(L, "reference pyargs or pykwargs invalid!"); } } else if (nargs == 2 && isargs && iskwargs) { args = get_pobject(L, largs); kwargs = get_pobject(L, lkwargs); // is args and kwargs ? // check the order (), {} if (PyTuple_Check(kwargs)) luaL_argerror(L, 1, "object tuple expected args(1,...)"); if (PyDict_Check(args)) luaL_argerror(L, 2, "object dict expected kwargs{a=1,...}"); } else if (nargs > 0) { python_setnumber(L, PY_LUA_TABLE_CONVERT, 1); args = get_py_tuple(L, 1); // arbitrary args fn(1,2,'a') python_setnumber(L, PY_LUA_TABLE_CONVERT, 0); isargs = false; } else { args = PyTuple_New(0); if (!args) lua_new_error(L, "#3 failed to create arguments tuple"); } value = PyObject_Call(pobj->object, args, kwargs); // fn(*args, **kwargs) if (!isargs) Py_DECREF(args); if (!iskwargs && kwargs) Py_DECREF(kwargs); if (value) { if (py_convert(L, value) == CONVERTED) { Py_DECREF(value); } } else { lua_raise_error(L, "call function python \"%s\"", pobj->object); } }
static int _p_object_index_get(lua_State *L, py_object *pobj, int keyn) { PyObject *key = LuaConvert(L, keyn); PyObject *item; int ret = 0; if (!key) luaL_argerror(L, 1, "failed to convert key"); if (pobj->asindx) { item = PyObject_GetItem(pobj->o, key); } else { item = PyObject_GetAttr(pobj->o, key); } Py_DECREF(key); if (item) { ret = py_convert(L, item); Py_DECREF(item); } else { PyErr_Clear(); char *keystr = get_pyobject_repr(L, key); char *error = "%s \"%s\" not found"; char *name = pobj->asindx ? "index or key" : "attribute"; char buff[strlen(error) + strlen(name) + strlen(keystr) + 1]; sprintf(buff, error, name, keystr); lua_error(L, &buff[0]); } return ret; }
static int get_py_object_index(lua_State *L, py_object *pobj, int keyn) { lua_Object lobj = lua_getparam(L, keyn); PyObject *key = lua_stack_convert(L, keyn, lobj); Conversion ret = UNCHANGED; PyObject *item; if (!key) luaL_argerror(L, 1, "failed to convert key"); if (pobj->asindx) { item = PyObject_GetItem(pobj->object, key); } else { item = PyObject_GetAttr(pobj->object, key); } if (item) { if ((ret = py_convert(L, item)) == CONVERTED) { Py_DECREF(item); } } else { char *error = "%s \"%s\" not found"; char *name = pobj->asindx ? "index" : "attribute"; char *mkey = get_pyobject_str(key); char *skey = mkey ? mkey : "..."; char buff[buffsize_calc(3, error, name, skey)]; sprintf(buff, error, name, skey); free(mkey); // free pointer! if (!is_object_container(L, lobj)) Py_DECREF(key); lua_new_error(L, buff); } if (!is_object_container(L, lobj)) Py_DECREF(key); return ret; }
static PyObject *LuaObject_getattr(PyObject *obj, PyObject *attr) { PyObject *ret; int rc; lua_rawgeti(LuaState, LUA_REGISTRYINDEX, ((LuaObject*)obj)->ref); if (lua_isnil(LuaState, -1)) { lua_pop(LuaState, 1); PyErr_SetString(PyExc_RuntimeError, "lost reference"); return NULL; } if (!lua_isstring(LuaState, -1) && !lua_istable(LuaState, -1) && !lua_isuserdata(LuaState, -1)) { lua_pop(LuaState, 1); PyErr_SetString(PyExc_RuntimeError, "not an indexable value"); return NULL; } ret = NULL; rc = py_convert(LuaState, attr, 0); if (rc) { lua_gettable(LuaState, -2); ret = LuaConvert(LuaState, -1); } else { PyErr_SetString(PyExc_ValueError, "can't convert attr/key"); } lua_settop(LuaState, 0); return ret; }
static void py_object_tostring(lua_State *L) { PyObject *obj = get_pobject(L, lua_getparam(L, 1)); if (PyString_Check(obj) || PyUnicode_Check(obj)) { py_convert(L, obj); } else { PyObject *repr = PyObject_Str(obj); if (!repr) { char buf[256]; snprintf(buf, 256, "python object: %p", obj); lua_pushstring(L, buf); PyErr_Clear(); } else { py_convert(L, repr); Py_DECREF(repr); } } }
/* python object presentation */ static char *get_pyobject_repr(lua_State *L, PyObject *pyobject) { char *repr = "..."; PyObject *str = PyObject_Str(pyobject); if (str && py_convert(L, str)) { lua_Object lstr = lua_pop(L); if (lua_isstring(L, lstr)) { repr = lua_getstring(L, lstr); } } return repr; }
static int py_run(lua_State *L, int eval) { const char *s; char *buffer = NULL; PyObject *m, *d, *o; int ret = 0; int len; s = luaL_checkstring(L, 1); if (!s) return 0; if (!eval) { len = strlen(s)+1; buffer = (char *) malloc(len+1); if (!buffer) { luaL_error(L, "Failed allocating buffer for execution"); return 0; } strcpy(buffer, s); buffer[len-1] = '\n'; buffer[len] = '\0'; s = buffer; } m = PyImport_AddModule("__main__"); if (!m) { free(buffer); luaL_error(L, "Can't get __main__ module"); return 0; } d = PyModule_GetDict(m); o = PyRun_StringFlags(s, eval ? Py_eval_input : Py_single_input, d, d, NULL); free(buffer); if (!o) { PyErr_Print(); return 0; } if (py_convert(L, o, 0)) ret = 1; Py_DECREF(o); if (Py_FlushLine()) PyErr_Clear(); return ret; }
static PyObject *Lua_to_table(PyObject *self, PyObject *args) { if (!PyTuple_Check(args)) { PyErr_SetString(PyExc_TypeError, "tuple expected"); lua_settop(LuaState, 0); return NULL; } PyObject *obj = PyTuple_GetItem(args, 0); if (PyDict_Check(obj)) { lua_newtable(LuaState); Py_ssize_t pos = 0; PyObject* key = NULL; PyObject* value = NULL; // key, value are borrowed while (PyDict_Next(obj, &pos, &key, &value)) { if (!key) { luaL_error(LuaState, "retrieve dictionary key"); } if (!value) { luaL_error(LuaState, "retrieve dictionary value"); } Py_INCREF(key); Py_INCREF(value); py_convert(LuaState, key, 0); py_convert(LuaState, value, 0); lua_rawset(LuaState, -3); } return LuaConvert(LuaState, -1); } PyErr_SetString(PyExc_TypeError, "dictionary expected"); lua_settop(LuaState, 0); return NULL; }
static int e_py_convert(lua_State *L, PyObject *o, int withnone) { int r = 0; TRY { r = py_convert(L, o, withnone); } CATCH { r = 0; } ENDTRY; if (!r) { PyErr_SetString(PyExc_RuntimeError, "can't convert"); } return r; }
static void py_object_tostring(lua_State *L) { py_object *obj = get_py_object(L, 1); if (obj) { PyObject *repr = PyObject_Str(obj->o); if (!repr) { char buf[256]; snprintf(buf, 256, "python object: %p", obj->o); lua_pushstring(L, buf); PyErr_Clear(); } else { py_convert(L, repr); Py_DECREF(repr); } } }
static void py_object_call(lua_State *L) { py_object *pobj = get_py_object(L, 1); PyObject *args; PyObject *value; int nargs = lua_gettop(L)-1; int i; if (!pobj) { luaL_argerror(L, 1, "not a python object"); } if (!PyCallable_Check(pobj->o)) { lua_error(L, "object is not callable"); } args = PyTuple_New(nargs); if (!args) { PyErr_Print(); lua_error(L, "failed to create arguments tuple"); } for (i = 0; i != nargs; i++) { PyObject *arg = LuaConvert(L, i + 2); if (!arg) { Py_DECREF(args); char *error = "failed to convert argument #%d"; char buff[strlen(error) + 10]; sprintf(buff, error, i + 1); lua_error(L, &buff[0]); } PyTuple_SetItem(args, i, arg); } value = PyObject_CallObject(pobj->o, args); if (value) { py_convert(L, value); Py_DECREF(value); } else { PyErr_Print(); char *name = get_pyobject_repr(L, pobj->o); char *error = "error calling python function \"%s\""; char buff[strlen(error) + strlen(name) + strlen(name) + 1]; sprintf(buff, error, name); lua_error(L, &buff[0]); } free(pobj); }
static int py_object_call(lua_State *L) { py_object *obj = (py_object*) luaL_checkudata(L, 1, POBJECT); PyObject *args; PyObject *value; int nargs = lua_gettop(L)-1; int ret = 0; int i; if (!obj) { luaL_argerror(L, 1, "not a python object"); return 0; } if (!PyCallable_Check(obj->o)) { luaL_error(L, "object is not callable"); return 0; } args = PyTuple_New(nargs); if (!args) { PyErr_Print(); luaL_error(L, "failed to create arguments tuple"); return 0; } for (i = 0; i != nargs; i++) { PyObject *arg = LuaConvert(L, i+2); if (!arg) { luaL_error(L, "failed to convert argument #%d", i+1); Py_DECREF(args); return 0; } PyTuple_SetItem(args, i, arg); } value = PyObject_CallObject(obj->o, args); if (value) { ret = py_convert(L, value, 0); Py_DECREF(value); } else { PyErr_Print(); luaL_error(L, "error calling python function"); } return ret; }
static int py_object_tostring(lua_State *L) { py_object *obj = (py_object*) luaL_checkudata(L, 1, POBJECT); if (obj) { PyObject *repr = PyObject_Str(obj->o); if (!repr) { char buf[256]; snprintf(buf, 256, "python object: %p", obj->o); lua_pushstring(L, buf); PyErr_Clear(); } else { py_convert(L, repr, 0); assert(lua_type(L, -1) == LUA_TSTRING); Py_DECREF(repr); } } return 1; }
static int py_run(lua_State *L, int eval) { const char *s; char *buffer = NULL; PyObject *m, *d, *o; Conversion ret; size_t len; s = luaL_check_string(L, 1); if (!s) return 0; if (!eval) { len = strlen(s) + 1; buffer = (char *) malloc(len + 1); if (!buffer) { lua_error(L, "Failed allocating buffer for execution"); } strcpy(buffer, s); buffer[len - 1] = '\n'; buffer[len] = '\0'; s = buffer; } m = PyImport_AddModule("__main__"); if (!m) { free(buffer); lua_error(L, "Can't get __main__ module"); } d = PyModule_GetDict(m); o = PyRun_StringFlags(s, eval ? Py_eval_input : Py_single_input, d, d, NULL); free(buffer); if (!o) { lua_new_error(L, "run custom code"); return 0; } if ((ret = py_convert(L, o)) == CONVERTED) { Py_DECREF(o); } #if PY_MAJOR_VERSION < 3 if (Py_FlushLine()) #endif PyErr_Clear(); return ret; }
static int py_object_index(lua_State *L) { py_object *obj = (py_object*) luaL_checkudata(L, 1, POBJECT); const char *attr; PyObject *value; int ret = 0; if (!obj) { luaL_argerror(L, 1, "not a python object"); return 0; } if (obj->asindx) return _p_object_index_get(L, obj, 2); attr = luaL_checkstring(L, 2); if (!attr) { luaL_argerror(L, 2, "string needed"); return 0; } if (attr[0] == '_' && strcmp(attr, "__get") == 0) { lua_pushvalue(L, 1); lua_pushcclosure(L, py_object_index_get, 1); return 1; } else if (attr[0] == '_' && strcmp(attr, "__set") == 0) { lua_pushvalue(L, 1); lua_pushcclosure(L, py_object_newindex_set, 1); return 1; } value = PyObject_GetAttrString(obj->o, (char*)attr); if (value) { ret = py_convert(L, value, 0); Py_DECREF(value); } else { PyErr_Clear(); luaL_error(L, "unknown attribute in python object"); } return ret; }
static PyObject *LuaCall(lua_State *L, PyObject *args) { PyObject *ret = NULL; PyObject *arg; int nargs, rc, i; if (!PyTuple_Check(args)) { PyErr_SetString(PyExc_TypeError, "tuple expected"); lua_settop(L, 0); return NULL; } nargs = PyTuple_Size(args); for (i = 0; i != nargs; i++) { arg = PyTuple_GetItem(args, i); if (arg == NULL) { PyErr_Format(PyExc_TypeError, "failed to get tuple item #%d", i); lua_settop(L, 0); return NULL; } rc = py_convert(L, arg, 0); if (!rc) { PyErr_Format(PyExc_TypeError, "failed to convert argument #%d", i); lua_settop(L, 0); return NULL; } } if (lua_pcall(L, nargs, LUA_MULTRET, 0) != 0) { PyErr_Format(PyExc_Exception, "error: %s", lua_tostring(L, -1)); return NULL; } nargs = lua_gettop(L); if (nargs == 1) { ret = LuaConvert(L, 1); if (!ret) { PyErr_SetString(PyExc_TypeError, "failed to convert return"); lua_settop(L, 0); Py_DECREF(ret); return NULL; } } else if (nargs > 1) { ret = PyTuple_New(nargs); if (!ret) { PyErr_SetString(PyExc_RuntimeError, "failed to create return tuple"); lua_settop(L, 0); return NULL; } for (i = 0; i != nargs; i++) { arg = LuaConvert(L, i+1); if (!arg) { PyErr_Format(PyExc_TypeError, "failed to convert return #%d", i); lua_settop(L, 0); Py_DECREF(ret); return NULL; } PyTuple_SetItem(ret, i, arg); } } else { Py_INCREF(Py_None); ret = Py_None; } lua_settop(L, 0); return ret; }