From cee0d8244d6b3223c296def49678076edb239445 Mon Sep 17 00:00:00 2001 From: Detlev Casanova Date: Tue, 6 Jul 2010 11:37:00 +0200 Subject: Now working execute function (only for functions) --- src/interpreter.c | 237 ++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 204 insertions(+), 33 deletions(-) diff --git a/src/interpreter.c b/src/interpreter.c index 6ab2843..2e2f7b9 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -2,57 +2,228 @@ #include #include -int main(int argc, char *argv[]) +/* + * PyObjectList + */ +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 *elementAt(PyObjectList* list, int pos) +{ + if (!list || list->count < pos) + return NULL; + + PyObjectListElem *node = list->root; + for (int i = 0; i < pos; i++) + { + node = node->next; + } + if (!node) + return 0; + + return node->object; +} + +PyObject *moduleNamed(const char *name, PyObjectList *list) +{ + PyObjectListElem *node = list->root; + while (node) + { + if (strcmp(PyModule_GetName(node->object), name)) + return node->object; + node = node->next; + } + + return NULL; +} + +PyObject *toTuple(PyObjectList *list) { - PyObject *pP1, *pP2, *pArgs, *pName, *pModule, *pDict, *pFunc, *pValue; + if (!list) + return NULL; - Py_Initialize(); + PyObject *ret = PyTuple_New(list->count); + PyObjectListElem *node = list->root; + int i = 0; + while (node) + { + if (node->object) + PyTuple_SetItem(ret, i++, node->object); + node = node->next; + } - //printf("%s\n", Py_GetVersion()); + return ret; +} - //pName = PyByteArray_FromStringAndSize("portage", strlen("portage")); - pModule = PyModule_New("portage"); +int listCount(PyObjectList *list) +{ + return (list ? list->count : 0); +} - pDict = PyModule_GetDict(pModule); - pFunc = PyDict_GetItemString(pDict, "pkgcmp"); +void freeList(PyObjectList *list, int deref) +{ + if (!list) + return; - if (PyCallable_Check(pFunc)) + PyObjectListElem *node = list->root; + while (node) { - pP1 = PyByteArray_FromStringAndSize("app-portage/kuroo4-4.2", strlen("app-portage/kuroo4-4.2")); - pP2 = PyByteArray_FromStringAndSize("app-portage/kuroo4-4.3", strlen("app-portage/kuroo4-4.3")); + PyObjectListElem *tmp = node; + node = node->next; + if (deref) + Py_DECREF(tmp->object); + free(tmp); + } - pArgs = PyTuple_New(2); + free(list); +} - PyTuple_SetItem(pArgs, 0, pP1); - PyTuple_SetItem(pArgs, 0, pP2); +/* + * Interpreter + */ - pValue = PyObject_CallObject(pFunc, pArgs); +/* + * A Python interpreter object keeps the context like the loaded modules. + */ - if (pArgs != NULL) +typedef struct Interpreter +{ + PyObjectList *modules; +} Interpreter; + +Interpreter *createInterpreter() +{ + Interpreter *ret = malloc(sizeof(Interpreter)); + ret->modules = createObjectList(); + return ret; +} + +void freeInterpreter(Interpreter *inter) +{ + if (!inter) + return; + freeList(inter->modules, 1); + free(inter); + + Py_Finalize(); +} + +/* + * printf() like function that executes a python function + * @param interpreter Python interpreter object on which the function should be ran + * @param module name of the python module in which the function is + * @param funcName the function name to call + * @param arg_types printf() like list of arguments TODO:explain more --> See Python documentation + * @param ... arguments for the function + */ + +PyObject *executeFunction(Interpreter *interpreter, const char *module, const char *funcName, const char* format, ...) +{ + if (!Py_IsInitialized()) + Py_Initialize(); + + // Make arguments + // FIXME: use Py_BuildValue. + // FIXME: is it possible to pass this function's arguments to another function ? + PyObjectList *argList = createObjectList(); + int i = 0; + while (format[i] != '\0') + { + while(format[i] != '%' && format[i] != '\0') + i++; + + if (format[i] == '\0') + break; + + PyObject *arg = NULL; + switch(format[++i]) { - Py_DECREF(pArgs); + case 'd': //number + break; + case 's': //string + break; + case 'P': //PyObject + break; + default: //skip or abort ? + break; } + + insert(argList, arg); + i++; } - else - PyErr_Print(); - int ret = PyLong_AsLong(pValue); - switch(ret) + PyObject *args = toTuple(argList); + freeList(argList, 1); + + // Look for the module. + PyObject *mod = 0; + if (interpreter->modules) { - case -1: - printf("less"); - break; - case 0: - printf("same"); - break; - case 1: - printf("more"); - break; + mod = moduleNamed(module, interpreter->modules); + } + if (!mod) + { + mod = PyImport_ImportModule(module); + insert(interpreter->modules, mod); } - printf("\n"); + // Look for the function + PyObject *dict = PyModule_GetDict(mod); + PyObject *func = PyDict_GetItemString(dict, funcName); - Py_DECREF(pModule); + if (!PyCallable_Check(func)) + return NULL; - Py_Finalize(); + // Call the function + PyObject *val = PyObject_CallObject(func, args); + + // Add return value object in a local list so it can be DECREF'ed when the interpreter is deleted. + // TODO + + Py_DECREF(args); + + return val; +} + + +int main(int argc, char *argv[]) +{ + Interpreter *in = createInterpreter(); + + PyObject *ret = executeFunction(in, "portage.data", "portage_group_warning", ""); + + if (!ret) + printf("failed :-( \n"); + + freeInterpreter(in); + + return 0; } -- cgit v1.2.3-1-g7c22