diff options
author | Detlev Casanova <detlev.casanova@gmail.com> | 2010-07-29 13:43:26 +0200 |
---|---|---|
committer | Detlev Casanova <detlev.casanova@gmail.com> | 2010-07-29 13:43:26 +0200 |
commit | e4edeb3446e6e6cbe38eee061d6e1cc60aa4b094 (patch) | |
tree | 566c386ca4de9c233acd19d1bb9609a09fbaa5c7 /src/interpreter.c | |
download | c-portage-e4edeb3446e6e6cbe38eee061d6e1cc60aa4b094.tar.gz c-portage-e4edeb3446e6e6cbe38eee061d6e1cc60aa4b094.tar.bz2 c-portage-e4edeb3446e6e6cbe38eee061d6e1cc60aa4b094.zip |
Initial library commit
Diffstat (limited to 'src/interpreter.c')
-rw-r--r-- | src/interpreter.c | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/src/interpreter.c b/src/interpreter.c new file mode 100644 index 0000000..941d2b2 --- /dev/null +++ b/src/interpreter.c @@ -0,0 +1,176 @@ +#include <Python.h> +#include <stdio.h> +#include <string.h> +#include "interpreter.h" + +/** + * PyObjectList + * 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); +} + +/* + * Interpreter + * + * A Python interpreter object keeps the context like the loaded modules. + */ + +struct Interpreter +{ + PyObjectList *modules; +} *in = 0; + +/** + * This is the first function that must be called before using the library. + */ +void portageInit() +{ + 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 portageFinalize() +{ + if (!in) + return; + freeList(in->modules, 1); + free(in); + + if (Py_IsInitialized()) + Py_Finalize(); +} + +/** + * 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, ...) +{ + if (!Py_IsInitialized()) + Py_Initialize(); + + // 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; +} |