You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucy.apache.org by ma...@apache.org on 2016/02/25 00:07:42 UTC
[15/20] lucy-clownfish git commit: Add helper routines for Python
callbacks.
Add helper routines for Python callbacks.
The generated C code for calling back into Python from Clownfish when a
method is overridden will require these helper functions for running the
Python callable, converting return values, etc.
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/bb7e8807
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/bb7e8807
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/bb7e8807
Branch: refs/heads/master
Commit: bb7e880799d6bb0e4743d24fcacb630e04b2e32f
Parents: 8996f0f
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Wed Jan 27 18:23:36 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Tue Feb 23 18:22:04 2016 -0800
----------------------------------------------------------------------
compiler/src/CFCPython.c | 203 +++++++++++++++++++++++++++++++++++++++++-
1 file changed, 202 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/bb7e8807/compiler/src/CFCPython.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPython.c b/compiler/src/CFCPython.c
index 10c9872..b39240d 100644
--- a/compiler/src/CFCPython.c
+++ b/compiler/src/CFCPython.c
@@ -137,7 +137,208 @@ S_gen_callbacks(CFCPython *self, CFCParcel *parcel, CFCClass **ordered) {
}
static const char helpers[] =
- ""
+ "static PyObject*\n"
+ "S_pack_tuple(int num_args, ...) {\n"
+ " PyObject *tuple = PyTuple_New(num_args);\n"
+ " va_list args;\n"
+ " va_start(args, num_args);\n"
+ " for (int i = 0; i < num_args; i++) {\n"
+ " PyObject *arg = va_arg(args, PyObject*);\n"
+ " PyTuple_SET_ITEM(tuple, i, arg);\n"
+ " }\n"
+ " va_end(args);\n"
+ " return tuple;\n"
+ "}\n"
+ "\n"
+ "static PyObject*\n"
+ "S_call_pymeth(PyObject *self, const char *meth_name, PyObject *args,\n"
+ " const char *file, int line, const char *func) {\n"
+ " PyObject *callable = PyObject_GetAttrString(self, meth_name);\n"
+ " if (!PyCallable_Check(callable)) {\n"
+ " cfish_String *mess\n"
+ " = cfish_Err_make_mess(file, line, func, \"Attr '%s' not callable\",\n"
+ " meth_name);\n"
+ " cfish_Err_throw_mess(CFISH_ERR, mess);\n"
+ " }\n"
+ " PyObject *result = PyObject_CallObject(callable, args);\n"
+ " Py_DECREF(args);\n"
+ " if (result == NULL) {\n"
+ " cfish_String *mess\n"
+ " = cfish_Err_make_mess(file, line, func,\n"
+ " \"Callback to '%s' failed\", meth_name);\n"
+ " CFBind_reraise_pyerr(CFISH_ERR, mess);\n"
+ " }\n"
+ " return result;\n"
+ "}\n"
+ "\n"
+ "#define CALL_PYMETH_VOID(self, meth_name, args) \\\n"
+ " S_call_pymeth_void(self, meth_name, args, \\\n"
+ " __FILE__, __LINE__, CFISH_ERR_FUNC_MACRO)\n"
+ "\n"
+ "static void\n"
+ "S_call_pymeth_void(PyObject *self, const char *meth_name, PyObject *args,\n"
+ " const char *file, int line, const char *func) {\n"
+ " PyObject *py_result\n"
+ " = S_call_pymeth(self, meth_name, args, file, line, func);\n"
+ " if (py_result == NULL) {\n"
+ " cfish_String *mess\n"
+ " = cfish_Err_make_mess(file, line, func, \"Call to %s failed\",\n"
+ " meth_name);\n"
+ " CFBind_reraise_pyerr(CFISH_ERR, mess);\n"
+ " }\n"
+ " Py_DECREF(py_result);\n"
+ "}\n"
+ "\n"
+ "#define CALL_PYMETH_BOOL(self, meth_name, args) \\\n"
+ " S_call_pymeth_bool(self, meth_name, args, \\\n"
+ " __FILE__, __LINE__, CFISH_ERR_FUNC_MACRO)\n"
+ "\n"
+ "static bool\n"
+ "S_call_pymeth_bool(PyObject *self, const char *meth_name, PyObject *args,\n"
+ " const char *file, int line, const char *func) {\n"
+ " PyObject *py_result\n"
+ " = S_call_pymeth(self, meth_name, args, file, line, func);\n"
+ " int truthiness = py_result != NULL\n"
+ " ? PyObject_IsTrue(py_result)\n"
+ " : -1;\n"
+ " if (truthiness == -1) {\n"
+ " cfish_String *mess\n"
+ " = cfish_Err_make_mess(file, line, func, \"Call to %s failed\",\n"
+ " meth_name);\n"
+ " CFBind_reraise_pyerr(CFISH_ERR, mess);\n"
+ " }\n"
+ " Py_DECREF(py_result);\n"
+ " return !!truthiness;\n"
+ "}\n"
+ "\n"
+ "#define CALL_PYMETH_OBJ(self, meth_name, args, ret_class, nullable) \\\n"
+ " S_call_pymeth_obj(self, meth_name, args, ret_class, nullable, \\\n"
+ " __FILE__, __LINE__, CFISH_ERR_FUNC_MACRO)\n"
+ "\n"
+ "static cfish_Obj*\n"
+ "S_call_pymeth_obj(PyObject *self, const char *meth_name,\n"
+ " PyObject *args, cfish_Class *ret_class, bool nullable,\n"
+ " const char *file, int line, const char *func) {\n"
+ " PyObject *py_result\n"
+ " = S_call_pymeth(self, meth_name, args, file, line, func);\n"
+ " cfish_Obj *result = CFBind_py_to_cfish(py_result, ret_class);\n"
+ " Py_DECREF(py_result);\n"
+ " if (!nullable && result == NULL) {\n"
+ " CFISH_THROW(CFISH_ERR, \"%s cannot return NULL\", meth_name);\n"
+ " }\n"
+ " else if (!cfish_Obj_is_a(result, ret_class)) {\n"
+ " cfish_Class *result_class = cfish_Obj_get_class(result);\n"
+ " CFISH_DECREF(result);\n"
+ " CFISH_THROW(CFISH_ERR, \"%s returned %o instead of %o\", meth_name,\n"
+ " CFISH_Class_Get_Name(result_class),\n"
+ " CFISH_Class_Get_Name(ret_class));\n"
+ " }\n"
+ " return result;\n"
+ "}\n"
+ "\n"
+ "#define CALL_PYMETH_DOUBLE(self, meth_name, args) \\\n"
+ " S_call_pymeth_f64(self, meth_name, args, \\\n"
+ " __FILE__, __LINE__, CFISH_ERR_FUNC_MACRO)\n"
+ "#define CALL_PYMETH_FLOAT(self, meth_name, args) \\\n"
+ " ((float)S_call_pymeth_f64(self, meth_name, args, \\\n"
+ " __FILE__, __LINE__, CFISH_ERR_FUNC_MACRO))\n"
+ "\n"
+ "static double\n"
+ "S_call_pymeth_f64(PyObject *self, const char *meth_name, PyObject *args,\n"
+ " const char *file, int line, const char *func) {\n"
+ " PyObject *py_result\n"
+ " = S_call_pymeth(self, meth_name, args, file, line, func);\n"
+ " PyErr_Clear();\n"
+ " double result = PyFloat_AsDouble(py_result);\n"
+ " if (PyErr_Occurred()) {\n"
+ " cfish_String *mess\n"
+ " = cfish_Err_make_mess(file, line, func,\n"
+ " \"Converting result of '%s' to double failed\",\n"
+ " meth_name);\n"
+ " CFBind_reraise_pyerr(CFISH_ERR, mess);\n"
+ " }\n"
+ " Py_DECREF(py_result);\n"
+ " return result;\n"
+ "}\n"
+ "\n"
+ "#define CALL_PYMETH_INT64_T(self, meth_name, args) \\\n"
+ " S_call_pymeth_i64(self, meth_name, args, INT64_MAX, INT64_MIN, \\\n"
+ " __FILE__, __LINE__, CFISH_ERR_FUNC_MACRO)\n"
+ "#define CALL_PYMETH_INT32_T(self, meth_name, args) \\\n"
+ " ((int32_t)S_call_pymeth_i64(self, meth_name, args, INT32_MAX, INT32_MIN, \\\n"
+ " __FILE__, __LINE__, CFISH_ERR_FUNC_MACRO))\n"
+ "#define CALL_PYMETH_INT16_T(self, meth_name, args) \\\n"
+ " ((int16_t)S_call_pymeth_i64(self, meth_name, args, INT16_MAX, INT16_MIN, \\\n"
+ " __FILE__, __LINE__, CFISH_ERR_FUNC_MACRO))\n"
+ "#define CALL_PYMETH_INT8_T(self, meth_name, args) \\\n"
+ " ((int8_t)S_call_pymeth_i64(self, meth_name, args, INT8_MAX, INT8_MIN, \\\n"
+ " __FILE__, __LINE__, CFISH_ERR_FUNC_MACRO))\n"
+ "#define CALL_PYMETH_CHAR(self, meth_name, args) \\\n"
+ " ((char)S_call_pymeth_i64(self, meth_name, args, CHAR_MAX, CHAR_MIN, \\\n"
+ " __FILE__, __LINE__, CFISH_ERR_FUNC_MACRO))\n"
+ "#define CALL_PYMETH_SHORT(self, meth_name, args) \\\n"
+ " ((short)S_call_pymeth_i64(self, meth_name, args, SHRT_MAX, SHRT_MIN, \\\n"
+ " __FILE__, __LINE__, CFISH_ERR_FUNC_MACRO))\n"
+ "#define CALL_PYMETH_INT(self, meth_name, args) \\\n"
+ " ((int16_t)S_call_pymeth_i64(self, meth_name, args, INT_MAX, INT_MIN, \\\n"
+ " __FILE__, __LINE__, CFISH_ERR_FUNC_MACRO))\n"
+ "#define CALL_PYMETH_LONG(self, meth_name, args) \\\n"
+ " ((int16_t)S_call_pymeth_i64(self, meth_name, args, LONG_MAX, LONG_MIN, \\\n"
+ " __FILE__, __LINE__, CFISH_ERR_FUNC_MACRO))\n"
+ "\n"
+ "static int64_t\n"
+ "S_call_pymeth_i64(PyObject *self, const char *meth_name, PyObject *args,\n"
+ " int64_t max, int64_t min,\n"
+ " const char *file, int line, const char *func) {\n"
+ " PyObject *py_result\n"
+ " = S_call_pymeth(self, meth_name, args, file, line, func);\n"
+ " PyErr_Clear();\n"
+ " int64_t result = PyLong_AsLongLong(py_result);\n"
+ " if (PyErr_Occurred() || result > max || result < min) {\n"
+ " cfish_String *mess\n"
+ " = cfish_Err_make_mess(file, line, func,\n"
+ " \"Converting result of '%s' to int64_t failed\",\n"
+ " meth_name);\n"
+ " CFBind_reraise_pyerr(CFISH_ERR, mess);\n"
+ " }\n"
+ " Py_DECREF(py_result);\n"
+ " return result;\n"
+ "}\n"
+ "\n"
+ "#define CALL_PYMETH_UINT64_T(self, meth_name, args) \\\n"
+ " S_call_pymeth_u64(self, meth_name, args, UINT64_MAX, \\\n"
+ " __FILE__, __LINE__, CFISH_ERR_FUNC_MACRO)\n"
+ "#define CALL_PYMETH_UINT32_T(self, meth_name, args) \\\n"
+ " ((uint32_t)S_call_pymeth_u64(self, meth_name, args, UINT32_MAX, \\\n"
+ " __FILE__, __LINE__, CFISH_ERR_FUNC_MACRO))\n"
+ "#define CALL_PYMETH_UINT16_T(self, meth_name, args) \\\n"
+ " ((uint32_t)S_call_pymeth_u64(self, meth_name, args, UINT16_MAX, \\\n"
+ " __FILE__, __LINE__, CFISH_ERR_FUNC_MACRO))\n"
+ "#define CALL_PYMETH_UINT8_T(self, meth_name, args) \\\n"
+ " ((uint32_t)S_call_pymeth_u64(self, meth_name, args, UINT8_MAX, \\\n"
+ " __FILE__, __LINE__, CFISH_ERR_FUNC_MACRO))\n"
+ "#define CALL_PYMETH_SIZE_T(self, meth_name, args) \\\n"
+ " S_call_pymeth_u64(self, meth_name, args, SIZE_MAX, \\\n"
+ " __FILE__, __LINE__, CFISH_ERR_FUNC_MACRO)\n"
+ "\n"
+ "static uint64_t\n"
+ "S_call_pymeth_u64(PyObject *self, const char *meth_name, PyObject *args,\n"
+ " uint64_t max,\n"
+ " const char *file, int line, const char *func) {\n"
+ " PyObject *py_result\n"
+ " = S_call_pymeth(self, meth_name, args, file, line, func);\n"
+ " PyErr_Clear();\n"
+ " uint64_t result = PyLong_AsUnsignedLongLong(py_result);\n"
+ " if (PyErr_Occurred()) {\n"
+ " cfish_String *mess\n"
+ " = cfish_Err_make_mess(file, line, func,\n"
+ " \"Converting result of '%s' to uint64_t failed\",\n"
+ " meth_name);\n"
+ " CFBind_reraise_pyerr(CFISH_ERR, mess);\n"
+ " }\n"
+ " Py_DECREF(py_result);\n"
+ " return result;\n"
+ "}\n"
;
static const char pattern[] =