diff options
author | Campbell Barton <ideasman42@gmail.com> | 2010-09-19 18:02:45 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2010-09-19 18:02:45 +0400 |
commit | 1615c9e435f83d8752f4cc50c9c6038ba4889514 (patch) | |
tree | a51e80291cfbdd2e92079f198564f05fa64198c2 /source/blender/python | |
parent | 6ed46566042760343029965f139d36473a077dcc (diff) |
python/c utility function for debugging, see http://wiki.blender.org/index.php/Dev:Doc/Debugging/PyFromC
Diffstat (limited to 'source/blender/python')
-rw-r--r-- | source/blender/python/generic/py_capi_utils.c | 145 | ||||
-rw-r--r-- | source/blender/python/generic/py_capi_utils.h | 2 |
2 files changed, 146 insertions, 1 deletions
diff --git a/source/blender/python/generic/py_capi_utils.c b/source/blender/python/generic/py_capi_utils.c index d964b766af7..d59624b54ab 100644 --- a/source/blender/python/generic/py_capi_utils.c +++ b/source/blender/python/generic/py_capi_utils.c @@ -291,3 +291,148 @@ PyObject *PyC_DefaultNameSpace(const char *filename) Py_INCREF(interp->builtins); /* AddObject steals a reference */ return PyModule_GetDict(mod_main); } + + +/* Would be nice if python had this built in */ +void PyC_RunQuicky(const char *filepath, int n, ...) +{ + FILE *fp= fopen(filepath, "r"); + + if(fp) { + PyGILState_STATE gilstate= PyGILState_Ensure(); + + va_list vargs; + + int *sizes= PyMem_MALLOC(sizeof(int) * (n / 2)); + int i; + + PyObject *py_dict = PyC_DefaultNameSpace(filepath); + PyObject *values= PyList_New(n / 2); /* namespace owns this, dont free */ + + PyObject *py_result, *ret; + + PyObject *struct_mod= PyImport_ImportModule("struct"); + PyObject *calcsize= PyObject_GetAttrString(struct_mod, "calcsize"); /* struct.calcsize */ + PyObject *pack= PyObject_GetAttrString(struct_mod, "pack"); /* struct.pack */ + PyObject *unpack= PyObject_GetAttrString(struct_mod, "unpack"); /* struct.unpack */ + + Py_DECREF(struct_mod); + + va_start(vargs, n); + for (i=0; i * 2<n; i++) { + char *format = va_arg(vargs, char *); + void *ptr = va_arg(vargs, void *); + + ret= PyObject_CallFunction(calcsize, "s", format); + + if(ret) { + sizes[i]= PyLong_AsSsize_t(ret); + Py_DECREF(ret); + ret = PyObject_CallFunction(unpack, "sy#", format, (char *)ptr, sizes[i]); + } + + if(ret == NULL) { + printf("PyC_InlineRun error, line:%d\n", __LINE__); + PyErr_Print(); + PyErr_Clear(); + + PyList_SET_ITEM(values, i, Py_None); /* hold user */ + Py_INCREF(Py_None); + + sizes[i]= 0; + } + else { + if(PyTuple_GET_SIZE(ret) == 1) { + /* convenience, convert single tuples into single values */ + PyObject *tmp= PyTuple_GET_ITEM(ret, 0); + Py_INCREF(tmp); + Py_DECREF(ret); + ret = tmp; + } + + PyList_SET_ITEM(values, i, ret); /* hold user */ + } + } + va_end(vargs); + + /* set the value so we can access it */ + PyDict_SetItemString(py_dict, "values", values); + + py_result = PyRun_File(fp, filepath, Py_file_input, py_dict, py_dict); + + fclose(fp); + + if(py_result) { + + /* we could skip this but then only slice assignment would work + * better not be so strict */ + values= PyDict_GetItemString(py_dict, "values"); + + if(values && PyList_Check(values)) { + + /* dont use the result */ + Py_DECREF(py_result); + py_result= NULL; + + /* now get the values back */ + va_start(vargs, n); + for (i=0; i*2 <n; i++) { + char *format = va_arg(vargs, char *); + void *ptr = va_arg(vargs, void *); + + PyObject *item; + PyObject *item_new; + /* prepend the string formatting and remake the tuple */ + item= PyList_GET_ITEM(values, i); + if(PyTuple_CheckExact(item)) { + int ofs= PyTuple_GET_SIZE(item); + item_new= PyTuple_New(ofs + 1); + while(ofs--) { + PyObject *member= PyTuple_GET_ITEM(item, ofs); + PyTuple_SET_ITEM(item_new, ofs + 1, member); + Py_INCREF(member); + } + + PyTuple_SET_ITEM(item_new, 0, PyUnicode_FromString(format)); + } + else { + item_new= Py_BuildValue("sO", format, item); + } + + ret = PyObject_Call(pack, item_new, NULL); + + if(ret) { + /* copy the bytes back into memory */ + memcpy(ptr, PyBytes_AS_STRING(ret), sizes[i]); + Py_DECREF(ret); + } + else { + printf("PyC_InlineRun error on arg '%d', line:%d\n", i, __LINE__); + PyC_ObSpit("failed converting:", item_new); + PyErr_Print(); + PyErr_Clear(); + } + + Py_DECREF(item_new); + } + va_end(vargs); + } + else { + printf("PyC_InlineRun error, 'values' not a list, line:%d\n", __LINE__); + } + } + else { + printf("PyC_InlineRun error line:%d\n", __LINE__); + PyErr_Print(); + PyErr_Clear(); + } + + Py_DECREF(calcsize); + Py_DECREF(pack); + Py_DECREF(unpack); + + PyMem_FREE(sizes); + + PyGILState_Release(gilstate); + } +} diff --git a/source/blender/python/generic/py_capi_utils.h b/source/blender/python/generic/py_capi_utils.h index 73769c91c76..b378f7a5a34 100644 --- a/source/blender/python/generic/py_capi_utils.h +++ b/source/blender/python/generic/py_capi_utils.h @@ -38,5 +38,5 @@ const char * PuC_UnicodeAsByte(PyObject *py_str, PyObject **coerce); /* coerce m /* name namespace function for bpy & bge */ PyObject * PyC_DefaultNameSpace(const char *filename); - +void PyC_RunQuicky(const char *filepath, int n, ...); #endif // PY_CAPI_UTILS_H |