From 78eefa4b5a74690a537fc725b4de2224548a0826 Mon Sep 17 00:00:00 2001 From: dol-sen Date: Wed, 5 Oct 2011 13:50:03 -0700 Subject: move everything to prep for a merge into layman. --- c-layman/src/interpreter.c | 189 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 189 insertions(+) create mode 100644 c-layman/src/interpreter.c (limited to 'c-layman/src/interpreter.c') diff --git a/c-layman/src/interpreter.c b/c-layman/src/interpreter.c new file mode 100644 index 0000000..95d40d9 --- /dev/null +++ b/c-layman/src/interpreter.c @@ -0,0 +1,189 @@ +#include +#include +#include +#include "interpreter.h" + +/** + * \internal + * Stores modules in a linked list so that they don't have to be reloaded every time. + */ +typedef struct PyObjectListElem +{ + PyObject *object; + struct PyObjectListElem *next; +} PyObjectListElem; + +typedef struct PyObjectList +{ + PyObjectListElem *root; + int count; +} PyObjectList; + +PyObjectList *createObjectList() +{ + PyObjectList *ret = malloc(sizeof(PyObjectList)); + ret->count = 0; + ret->root = 0; + return ret; +} + +void insert(PyObjectList* list, PyObject *object) +{ + if (!list || !object) + return; + PyObjectListElem *node = malloc(sizeof(PyObjectListElem)); + node->object = object; + node->next = list->root; + list->root = node; + list->count++; +} + +PyObject *moduleNamed(const char *name, PyObjectList *list) +{ + PyObjectListElem *node = list->root; + while (node) + { + if (strcmp(PyModule_GetName(node->object), name) == 0) + return node->object; + node = node->next; + } + + return NULL; +} + +int listCount(PyObjectList *list) +{ + return (list ? list->count : 0); +} + +void freeList(PyObjectList *list, int deref) +{ + if (!list) + return; + + PyObjectListElem *node = list->root; + while (node) + { + PyObjectListElem *tmp = node; + node = node->next; + if (deref) + { + Py_DECREF(tmp->object); + } + free(tmp); + } + + free(list); +} + +/** + * \internal + * A Python interpreter object keeps the context like the loaded modules. + */ +struct Interpreter +{ + PyObjectList *modules; +} *in = 0; + + +/** \defgroup layman_base Layman base + * + * \brief Layman Base functions + * + * These functions are used when you want to begin or end using the library. + */ + +/** \addtogroup layman_base + * @{ + */ + +/** + * This is the first function that must be called before using the library. + * It initializes the Python interpreter. + */ +void laymanInit() +{ + if (in) + return; + + if (!Py_IsInitialized()) + Py_Initialize(); + + in = malloc(sizeof(struct Interpreter)); + in->modules = createObjectList(); +} + +/** + * Call this function when you're done using the library. + * It will free memory. + */ +void laymanFinalize() +{ + if (!in) + return; + freeList(in->modules, 1); + free(in); + + if (Py_IsInitialized()) + Py_Finalize(); +} + +/** @} */ + +/** + * \internal + * printf() like function that executes a python function + * + * \param module name of the python module in which the function is + * \param funcName the function name to call + * \param format printf() like list of arguments. See Python documentation + * \param ... arguments for the function + * + * \return the result of the execution. Can be NULL if the call failed. + */ +PyObject *executeFunction(const char *module, const char *funcName, const char* format, ...) +{ + assert(in); + + // Make argument list + PyObject *args; + if (format == NULL || strcmp(format, "") == 0) + args = PyTuple_New(0); + else + { + va_list listArgs; + va_start(listArgs, format); + + args = Py_VaBuildValue(format, listArgs); + } + + // Look for the module. + PyObject *mod = 0; + if (in->modules) + { + mod = moduleNamed(module, in->modules); + } + // If module is not loaded yet, do it. + if (!mod) + { + mod = PyImport_ImportModule(module); + if (!mod) + return NULL; + insert(in->modules, mod); + } + + // Look for the function + PyObject *func = PyObject_GetAttrString(mod, funcName); + if (!PyCallable_Check(func)) + return NULL; + + // Execute it + PyObject *val = PyObject_CallObject(func, args); + + if (args != NULL) + { + Py_DECREF(args); + } + + return val; +} -- cgit v1.2.3-1-g7c22