b8537a1359f3fce8c81f272a87ae2b8c51ea95b4
[blender.git] / source / blender / python / generic / py_capi_utils.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * ***** END GPL LICENSE BLOCK *****
19  */
20
21 /** \file blender/python/generic/py_capi_utils.c
22  *  \ingroup pygen
23  *
24  * Extend upon CPython's API, filling in some gaps, these functions use PyC_
25  * prefix to distinguish them apart from CPython.
26  *
27  * \note
28  * This module should only depend on CPython, however it currently uses
29  * BLI_string_utf8() for unicode conversion.
30  */
31
32
33 #include <Python.h>
34 #include <frameobject.h>
35
36 #include "py_capi_utils.h"
37
38 /* only for BLI_strncpy_wchar_from_utf8, should replace with py funcs but too late in release now */
39 #include "BLI_string_utf8.h"
40
41 #ifdef _WIN32 /* BLI_setenv */
42 #include "BLI_path_util.h"
43 #endif
44
45 /* array utility function */
46 int PyC_AsArray(void *array, PyObject *value, const Py_ssize_t length,
47                 const PyTypeObject *type, const short is_double, const char *error_prefix)
48 {
49         PyObject *value_fast;
50         Py_ssize_t value_len;
51         Py_ssize_t i;
52
53         if (!(value_fast = PySequence_Fast(value, error_prefix))) {
54                 return -1;
55         }
56
57         value_len = PySequence_Fast_GET_SIZE(value_fast);
58
59         if (value_len != length) {
60                 Py_DECREF(value);
61                 PyErr_Format(PyExc_TypeError,
62                              "%.200s: invalid sequence length. expected %d, got %d",
63                              error_prefix, length, value_len);
64                 return -1;
65         }
66
67         /* for each type */
68         if (type == &PyFloat_Type) {
69                 if (is_double) {
70                         double *array_double = array;
71                         for (i = 0; i < length; i++) {
72                                 array_double[i] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value_fast, i));
73                         }
74                 }
75                 else {
76                         float *array_float = array;
77                         for (i = 0; i < length; i++) {
78                                 array_float[i] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value_fast, i));
79                         }
80                 }
81         }
82         else if (type == &PyLong_Type) {
83                 /* could use is_double for 'long int' but no use now */
84                 int *array_int = array;
85                 for (i = 0; i < length; i++) {
86                         array_int[i] = PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value_fast, i));
87                 }
88         }
89         else if (type == &PyBool_Type) {
90                 int *array_bool = array;
91                 for (i = 0; i < length; i++) {
92                         array_bool[i] = (PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value_fast, i)) != 0);
93                 }
94         }
95         else {
96                 Py_DECREF(value_fast);
97                 PyErr_Format(PyExc_TypeError,
98                              "%s: internal error %s is invalid",
99                              error_prefix, type->tp_name);
100                 return -1;
101         }
102
103         Py_DECREF(value_fast);
104
105         if (PyErr_Occurred()) {
106                 PyErr_Format(PyExc_TypeError,
107                              "%s: one or more items could not be used as a %s",
108                              error_prefix, type->tp_name);
109                 return -1;
110         }
111
112         return 0;
113 }
114
115
116 /* for debugging */
117 void PyC_ObSpit(const char *name, PyObject *var)
118 {
119         fprintf(stderr, "<%s> : ", name);
120         if (var == NULL) {
121                 fprintf(stderr, "<NIL>");
122         }
123         else {
124                 PyObject_Print(var, stderr, 0);
125                 fprintf(stderr, " ref:%d ", (int)var->ob_refcnt);
126                 fprintf(stderr, " ptr:%p", (void *)var);
127                 
128                 fprintf(stderr, " type:");
129                 if (Py_TYPE(var))
130                         fprintf(stderr, "%s", Py_TYPE(var)->tp_name);
131                 else
132                         fprintf(stderr, "<NIL>");
133         }
134         fprintf(stderr, "\n");
135 }
136
137 void PyC_LineSpit(void)
138 {
139
140         const char *filename;
141         int lineno;
142
143         /* Note, allow calling from outside python (RNA) */
144         if (!PYC_INTERPRETER_ACTIVE) {
145                 fprintf(stderr, "python line lookup failed, interpreter inactive\n");
146                 return;
147         }
148
149         PyErr_Clear();
150         PyC_FileAndNum(&filename, &lineno);
151         
152         fprintf(stderr, "%s:%d\n", filename, lineno);
153 }
154
155 void PyC_StackSpit(void)
156 {
157         /* Note, allow calling from outside python (RNA) */
158         if (!PYC_INTERPRETER_ACTIVE) {
159                 fprintf(stderr, "python line lookup failed, interpreter inactive\n");
160                 return;
161         }
162         else {
163                 /* lame but handy */
164                 PyGILState_STATE gilstate = PyGILState_Ensure();
165                 PyRun_SimpleString("__import__('traceback').print_stack()");
166                 PyGILState_Release(gilstate);
167         }
168 }
169
170 void PyC_FileAndNum(const char **filename, int *lineno)
171 {
172         PyFrameObject *frame;
173         
174         if (filename) *filename = NULL;
175         if (lineno)   *lineno = -1;
176
177         if (!(frame = PyThreadState_GET()->frame)) {
178                 return;
179         }
180
181         /* when executing a script */
182         if (filename) {
183                 *filename = _PyUnicode_AsString(frame->f_code->co_filename);
184         }
185
186         /* when executing a module */
187         if (filename && *filename == NULL) {
188                 /* try an alternative method to get the filename - module based
189                  * references below are all borrowed (double checked) */
190                 PyObject *mod_name = PyDict_GetItemString(PyEval_GetGlobals(), "__name__");
191                 if (mod_name) {
192                         PyObject *mod = PyDict_GetItem(PyImport_GetModuleDict(), mod_name);
193                         if (mod) {
194                                 *filename = PyModule_GetFilename(mod);
195                         }
196
197                         /* unlikely, fallback */
198                         if (*filename == NULL) {
199                                 *filename = _PyUnicode_AsString(mod_name);
200                         }
201                 }
202         }
203
204         if (lineno) {
205                 *lineno = PyFrame_GetLineNumber(frame);
206         }
207 }
208
209 void PyC_FileAndNum_Safe(const char **filename, int *lineno)
210 {
211         if (!PYC_INTERPRETER_ACTIVE) {
212                 return;
213         }
214
215         PyC_FileAndNum(filename, lineno);
216 }
217
218 /* Would be nice if python had this built in */
219 PyObject *PyC_Object_GetAttrStringArgs(PyObject *o, Py_ssize_t n, ...)
220 {
221         Py_ssize_t i;
222         PyObject *item = o;
223         char *attr;
224         
225         va_list vargs;
226
227         va_start(vargs, n);
228         for (i = 0; i < n; i++) {
229                 attr = va_arg(vargs, char *);
230                 item = PyObject_GetAttrString(item, attr);
231                 
232                 if (item) 
233                         Py_DECREF(item);
234                 else /* python will set the error value here */
235                         break;
236                 
237         }
238         va_end(vargs);
239         
240         Py_XINCREF(item); /* final value has is increfed, to match PyObject_GetAttrString */
241         return item;
242 }
243
244 /* similar to PyErr_Format(),
245  *
246  * implementation - we cant actually preprend the existing exception,
247  * because it could have _any_ arguments given to it, so instead we get its
248  * __str__ output and raise our own exception including it.
249  */
250 PyObject *PyC_Err_Format_Prefix(PyObject *exception_type_prefix, const char *format, ...)
251 {
252         PyObject *error_value_prefix;
253         va_list args;
254
255         va_start(args, format);
256         error_value_prefix = PyUnicode_FromFormatV(format, args); /* can fail and be NULL */
257         va_end(args);
258
259         if (PyErr_Occurred()) {
260                 PyObject *error_type, *error_value, *error_traceback;
261                 PyErr_Fetch(&error_type, &error_value, &error_traceback);
262                 PyErr_Format(exception_type_prefix,
263                              "%S, %.200s(%S)",
264                              error_value_prefix,
265                              Py_TYPE(error_value)->tp_name,
266                              error_value
267                              );
268         }
269         else {
270                 PyErr_SetObject(exception_type_prefix,
271                                 error_value_prefix
272                                 );
273         }
274
275         Py_XDECREF(error_value_prefix);
276
277         /* dumb to always return NULL but matches PyErr_Format */
278         return NULL;
279 }
280
281
282 /* returns the exception string as a new PyUnicode object, depends on external traceback module */
283 #if 0
284
285 /* this version uses traceback module but somehow fails on UI errors */
286
287 PyObject *PyC_ExceptionBuffer(void)
288 {
289         PyObject *traceback_mod = NULL;
290         PyObject *format_tb_func = NULL;
291         PyObject *ret = NULL;
292
293         if (!(traceback_mod = PyImport_ImportModule("traceback"))) {
294                 goto error_cleanup;
295         }
296         else if (!(format_tb_func = PyObject_GetAttrString(traceback_mod, "format_exc"))) {
297                 goto error_cleanup;
298         }
299
300         ret = PyObject_CallObject(format_tb_func, NULL);
301
302         if (ret == Py_None) {
303                 Py_DECREF(ret);
304                 ret = NULL;
305         }
306
307 error_cleanup:
308         /* could not import the module so print the error and close */
309         Py_XDECREF(traceback_mod);
310         Py_XDECREF(format_tb_func);
311
312         return ret;
313 }
314 #else /* verbose, non-threadsafe version */
315 PyObject *PyC_ExceptionBuffer(void)
316 {
317         PyObject *stdout_backup = PySys_GetObject("stdout"); /* borrowed */
318         PyObject *stderr_backup = PySys_GetObject("stderr"); /* borrowed */
319         PyObject *string_io = NULL;
320         PyObject *string_io_buf = NULL;
321         PyObject *string_io_mod = NULL;
322         PyObject *string_io_getvalue = NULL;
323
324         PyObject *error_type, *error_value, *error_traceback;
325
326         if (!PyErr_Occurred())
327                 return NULL;
328
329         PyErr_Fetch(&error_type, &error_value, &error_traceback);
330
331         PyErr_Clear();
332
333         /* import io
334          * string_io = io.StringIO()
335          */
336
337         if (!(string_io_mod = PyImport_ImportModule("io"))) {
338                 goto error_cleanup;
339         }
340         else if (!(string_io = PyObject_CallMethod(string_io_mod, (char *)"StringIO", NULL))) {
341                 goto error_cleanup;
342         }
343         else if (!(string_io_getvalue = PyObject_GetAttrString(string_io, "getvalue"))) {
344                 goto error_cleanup;
345         }
346
347         Py_INCREF(stdout_backup); // since these were borrowed we don't want them freed when replaced.
348         Py_INCREF(stderr_backup);
349
350         PySys_SetObject("stdout", string_io); // both of these are freed when restoring
351         PySys_SetObject("stderr", string_io);
352
353         PyErr_Restore(error_type, error_value, error_traceback);
354         PyErr_Print(); /* print the error */
355         PyErr_Clear();
356
357         string_io_buf = PyObject_CallObject(string_io_getvalue, NULL);
358
359         PySys_SetObject("stdout", stdout_backup);
360         PySys_SetObject("stderr", stderr_backup);
361
362         Py_DECREF(stdout_backup); /* now sys owns the ref again */
363         Py_DECREF(stderr_backup);
364
365         Py_DECREF(string_io_mod);
366         Py_DECREF(string_io_getvalue);
367         Py_DECREF(string_io); /* free the original reference */
368
369         PyErr_Clear();
370         return string_io_buf;
371
372
373 error_cleanup:
374         /* could not import the module so print the error and close */
375         Py_XDECREF(string_io_mod);
376         Py_XDECREF(string_io);
377
378         PyErr_Restore(error_type, error_value, error_traceback);
379         PyErr_Print(); /* print the error */
380         PyErr_Clear();
381
382         return NULL;
383 }
384 #endif
385
386
387 /* string conversion, escape non-unicode chars, coerce must be set to NULL */
388 const char *PyC_UnicodeAsByte(PyObject *py_str, PyObject **coerce)
389 {
390         const char *result;
391
392         result = _PyUnicode_AsString(py_str);
393
394         if (result) {
395                 /* 99% of the time this is enough but we better support non unicode
396                  * chars since blender doesnt limit this */
397                 return result;
398         }
399         else {
400                 PyErr_Clear();
401
402                 if (PyBytes_Check(py_str)) {
403                         return PyBytes_AS_STRING(py_str);
404                 }
405 #ifdef WIN32
406                 /* bug [#31856] oddly enough, Python3.2 --> 3.3 on Windows will throw an
407                  * exception here this needs to be fixed in python:
408                  * see: bugs.python.org/issue15859 */
409                 else if (!PyUnicode_Check(py_str)) {
410                         PyErr_BadArgument();
411                         return NULL;
412                 }
413 #endif
414                 else if ((*coerce = PyUnicode_EncodeFSDefault(py_str))) {
415                         return PyBytes_AS_STRING(*coerce);
416                 }
417                 else {
418                         /* leave error raised from EncodeFS */
419                         return NULL;
420                 }
421         }
422 }
423
424 PyObject *PyC_UnicodeFromByteAndSize(const char *str, Py_ssize_t size)
425 {
426         PyObject *result = PyUnicode_FromStringAndSize(str, size);
427         if (result) {
428                 /* 99% of the time this is enough but we better support non unicode
429                  * chars since blender doesnt limit this */
430                 return result;
431         }
432         else {
433                 PyErr_Clear();
434                 /* this means paths will always be accessible once converted, on all OS's */
435                 result = PyUnicode_DecodeFSDefaultAndSize(str, size);
436                 return result;
437         }
438 }
439
440 PyObject *PyC_UnicodeFromByte(const char *str)
441 {
442         return PyC_UnicodeFromByteAndSize(str, strlen(str));
443 }
444
445 /*****************************************************************************
446  * Description: This function creates a new Python dictionary object.
447  * note: dict is owned by sys.modules["__main__"] module, reference is borrowed
448  * note: important we use the dict from __main__, this is what python expects
449  *  for 'pickle' to work as well as strings like this...
450  * >> foo = 10
451  * >> print(__import__("__main__").foo)
452  *
453  * note: this overwrites __main__ which gives problems with nested calls.
454  * be sure to run PyC_MainModule_Backup & PyC_MainModule_Restore if there is
455  * any chance that python is in the call stack.
456  ****************************************************************************/
457 PyObject *PyC_DefaultNameSpace(const char *filename)
458 {
459         PyInterpreterState *interp = PyThreadState_GET()->interp;
460         PyObject *mod_main = PyModule_New("__main__");
461         PyDict_SetItemString(interp->modules, "__main__", mod_main);
462         Py_DECREF(mod_main); /* sys.modules owns now */
463         PyModule_AddStringConstant(mod_main, "__name__", "__main__");
464         if (filename) {
465                 /* __file__ mainly for nice UI'ness */
466                 PyModule_AddObject(mod_main, "__file__", PyUnicode_DecodeFSDefault(filename));
467         }
468         PyModule_AddObject(mod_main, "__builtins__", interp->builtins);
469         Py_INCREF(interp->builtins); /* AddObject steals a reference */
470         return PyModule_GetDict(mod_main);
471 }
472
473 /* restore MUST be called after this */
474 void PyC_MainModule_Backup(PyObject **main_mod)
475 {
476         PyInterpreterState *interp = PyThreadState_GET()->interp;
477         *main_mod = PyDict_GetItemString(interp->modules, "__main__");
478         Py_XINCREF(*main_mod); /* don't free */
479 }
480
481 void PyC_MainModule_Restore(PyObject *main_mod)
482 {
483         PyInterpreterState *interp = PyThreadState_GET()->interp;
484         PyDict_SetItemString(interp->modules, "__main__", main_mod);
485         Py_XDECREF(main_mod);
486 }
487
488 /* must be called before Py_Initialize, expects output of BLI_get_folder(BLENDER_PYTHON, NULL) */
489 void PyC_SetHomePath(const char *py_path_bundle)
490 {
491         if (py_path_bundle == NULL) {
492                 /* Common enough to have bundled *nix python but complain on OSX/Win */
493 #if defined(__APPLE__) || defined(_WIN32)
494                 fprintf(stderr, "Warning! bundled python not found and is expected on this platform. "
495                         "(if you built with CMake: 'install' target may have not been built)\n");
496 #endif
497                 return;
498         }
499         /* set the environment path */
500         printf("found bundled python: %s\n", py_path_bundle);
501
502 #ifdef __APPLE__
503         /* OSX allow file/directory names to contain : character (represented as / in the Finder)
504          * but current Python lib (release 3.1.1) doesn't handle these correctly */
505         if (strchr(py_path_bundle, ':'))
506                 printf("Warning : Blender application is located in a path containing : or / chars\
507                        \nThis may make python import function fail\n");
508 #endif
509
510
511 #if 0 /* disable for now [#31506] - campbell */
512 #ifdef _WIN32
513         /* cmake/MSVC debug build crashes without this, why only
514          * in this case is unknown.. */
515         {
516                 /*BLI_setenv("PYTHONPATH", py_path_bundle)*/;
517         }
518 #endif
519 #endif
520
521         {
522                 static wchar_t py_path_bundle_wchar[1024];
523
524                 /* cant use this, on linux gives bug: #23018, TODO: try LANG="en_US.UTF-8" /usr/bin/blender, suggested 22008 */
525                 /* mbstowcs(py_path_bundle_wchar, py_path_bundle, FILE_MAXDIR); */
526
527                 BLI_strncpy_wchar_from_utf8(py_path_bundle_wchar, py_path_bundle,
528                                             sizeof(py_path_bundle_wchar) / sizeof(wchar_t));
529
530                 Py_SetPythonHome(py_path_bundle_wchar);
531                 // printf("found python (wchar_t) '%ls'\n", py_path_bundle_wchar);
532         }
533 }
534
535 /* Would be nice if python had this built in
536  * See: http://wiki.blender.org/index.php/Dev:Doc/Tools/Debugging/PyFromC
537  */
538 void PyC_RunQuicky(const char *filepath, int n, ...)
539 {
540         FILE *fp = fopen(filepath, "r");
541
542         if (fp) {
543                 PyGILState_STATE gilstate = PyGILState_Ensure();
544
545                 va_list vargs;
546
547                 int *sizes = PyMem_MALLOC(sizeof(int) * (n / 2));
548                 int i;
549
550                 PyObject *py_dict = PyC_DefaultNameSpace(filepath);
551                 PyObject *values = PyList_New(n / 2); /* namespace owns this, don't free */
552
553                 PyObject *py_result, *ret;
554
555                 PyObject *struct_mod = PyImport_ImportModule("struct");
556                 PyObject *calcsize = PyObject_GetAttrString(struct_mod, "calcsize"); /* struct.calcsize */
557                 PyObject *pack = PyObject_GetAttrString(struct_mod, "pack"); /* struct.pack */
558                 PyObject *unpack = PyObject_GetAttrString(struct_mod, "unpack"); /* struct.unpack */
559
560                 Py_DECREF(struct_mod);
561
562                 va_start(vargs, n);
563                 for (i = 0; i * 2 < n; i++) {
564                         char *format = va_arg(vargs, char *);
565                         void *ptr = va_arg(vargs, void *);
566
567                         ret = PyObject_CallFunction(calcsize, (char *)"s", format);
568
569                         if (ret) {
570                                 sizes[i] = PyLong_AsSsize_t(ret);
571                                 Py_DECREF(ret);
572                                 ret = PyObject_CallFunction(unpack, (char *)"sy#", format, (char *)ptr, sizes[i]);
573                         }
574
575                         if (ret == NULL) {
576                                 printf("PyC_InlineRun error, line:%d\n", __LINE__);
577                                 PyErr_Print();
578                                 PyErr_Clear();
579
580                                 PyList_SET_ITEM(values, i, Py_None); /* hold user */
581                                 Py_INCREF(Py_None);
582
583                                 sizes[i] = 0;
584                         }
585                         else {
586                                 if (PyTuple_GET_SIZE(ret) == 1) {
587                                         /* convenience, convert single tuples into single values */
588                                         PyObject *tmp = PyTuple_GET_ITEM(ret, 0);
589                                         Py_INCREF(tmp);
590                                         Py_DECREF(ret);
591                                         ret = tmp;
592                                 }
593
594                                 PyList_SET_ITEM(values, i, ret); /* hold user */
595                         }
596                 }
597                 va_end(vargs);
598                 
599                 /* set the value so we can access it */
600                 PyDict_SetItemString(py_dict, "values", values);
601
602                 py_result = PyRun_File(fp, filepath, Py_file_input, py_dict, py_dict);
603
604                 fclose(fp);
605
606                 if (py_result) {
607
608                         /* we could skip this but then only slice assignment would work
609                          * better not be so strict */
610                         values = PyDict_GetItemString(py_dict, "values");
611
612                         if (values && PyList_Check(values)) {
613
614                                 /* don't use the result */
615                                 Py_DECREF(py_result);
616                                 py_result = NULL;
617
618                                 /* now get the values back */
619                                 va_start(vargs, n);
620                                 for (i = 0; i * 2 < n; i++) {
621                                         char *format = va_arg(vargs, char *);
622                                         void *ptr = va_arg(vargs, void *);
623                                         
624                                         PyObject *item;
625                                         PyObject *item_new;
626                                         /* prepend the string formatting and remake the tuple */
627                                         item = PyList_GET_ITEM(values, i);
628                                         if (PyTuple_CheckExact(item)) {
629                                                 int ofs = PyTuple_GET_SIZE(item);
630                                                 item_new = PyTuple_New(ofs + 1);
631                                                 while (ofs--) {
632                                                         PyObject *member = PyTuple_GET_ITEM(item, ofs);
633                                                         PyTuple_SET_ITEM(item_new, ofs + 1, member);
634                                                         Py_INCREF(member);
635                                                 }
636
637                                                 PyTuple_SET_ITEM(item_new, 0, PyUnicode_FromString(format));
638                                         }
639                                         else {
640                                                 item_new = Py_BuildValue("sO", format, item);
641                                         }
642
643                                         ret = PyObject_Call(pack, item_new, NULL);
644
645                                         if (ret) {
646                                                 /* copy the bytes back into memory */
647                                                 memcpy(ptr, PyBytes_AS_STRING(ret), sizes[i]);
648                                                 Py_DECREF(ret);
649                                         }
650                                         else {
651                                                 printf("PyC_InlineRun error on arg '%d', line:%d\n", i, __LINE__);
652                                                 PyC_ObSpit("failed converting:", item_new);
653                                                 PyErr_Print();
654                                                 PyErr_Clear();
655                                         }
656
657                                         Py_DECREF(item_new);
658                                 }
659                                 va_end(vargs);
660                         }
661                         else {
662                                 printf("PyC_InlineRun error, 'values' not a list, line:%d\n", __LINE__);
663                         }
664                 }
665                 else {
666                         printf("PyC_InlineRun error line:%d\n", __LINE__);
667                         PyErr_Print();
668                         PyErr_Clear();
669                 }
670
671                 Py_DECREF(calcsize);
672                 Py_DECREF(pack);
673                 Py_DECREF(unpack);
674
675                 PyMem_FREE(sizes);
676
677                 PyGILState_Release(gilstate);
678         }
679 }
680
681 /* generic function to avoid depending on RNA */
682 void *PyC_RNA_AsPointer(PyObject *value, const char *type_name)
683 {
684         PyObject *as_pointer;
685         PyObject *pointer;
686
687         if (!strcmp(Py_TYPE(value)->tp_name, type_name) &&
688             (as_pointer = PyObject_GetAttrString(value, "as_pointer")) != NULL &&
689             PyCallable_Check(as_pointer))
690         {
691                 void *result = NULL;
692
693                 /* must be a 'type_name' object */
694                 pointer = PyObject_CallObject(as_pointer, NULL);
695                 Py_DECREF(as_pointer);
696
697                 if (!pointer) {
698                         PyErr_SetString(PyExc_SystemError, "value.as_pointer() failed");
699                         return NULL;
700                 }
701                 result = PyLong_AsVoidPtr(pointer);
702                 Py_DECREF(pointer);
703                 if (!result) {
704                         PyErr_SetString(PyExc_SystemError, "value.as_pointer() failed");
705                 }
706
707                 return result;
708         }
709         else {
710                 PyErr_Format(PyExc_TypeError,
711                              "expected '%.200s' type found '%.200s' instead",
712                              type_name, Py_TYPE(value)->tp_name);
713                 return NULL;
714         }
715 }
716
717
718 /* PyC_FlagSet_* functions - so flags/sets can be interchanged in a generic way */
719 #include "BLI_dynstr.h"
720 #include "MEM_guardedalloc.h"
721
722 char *PyC_FlagSet_AsString(PyC_FlagSet *item)
723 {
724         DynStr *dynstr = BLI_dynstr_new();
725         PyC_FlagSet *e;
726         char *cstring;
727
728         for (e = item; item->identifier; item++) {
729                 BLI_dynstr_appendf(dynstr, (e == item) ? "'%s'" : ", '%s'", item->identifier);
730         }
731
732         cstring = BLI_dynstr_get_cstring(dynstr);
733         BLI_dynstr_free(dynstr);
734         return cstring;
735 }
736
737 int PyC_FlagSet_ValueFromID_int(PyC_FlagSet *item, const char *identifier, int *value)
738 {
739         for ( ; item->identifier; item++) {
740                 if (strcmp(item->identifier, identifier) == 0) {
741                         *value = item->value;
742                         return 1;
743                 }
744         }
745
746         return 0;
747 }
748
749 int PyC_FlagSet_ValueFromID(PyC_FlagSet *item, const char *identifier, int *value, const char *error_prefix)
750 {
751         if (PyC_FlagSet_ValueFromID_int(item, identifier, value) == 0) {
752                 const char *enum_str = PyC_FlagSet_AsString(item);
753                 PyErr_Format(PyExc_ValueError,
754                              "%s: '%.200s' not found in (%s)",
755                              error_prefix, identifier, enum_str);
756                 MEM_freeN((void *)enum_str);
757                 return -1;
758         }
759
760         return 0;
761 }
762
763 int PyC_FlagSet_ToBitfield(PyC_FlagSet *items, PyObject *value, int *r_value, const char *error_prefix)
764 {
765         /* set of enum items, concatenate all values with OR */
766         int ret, flag = 0;
767
768         /* set looping */
769         Py_ssize_t pos = 0;
770         Py_ssize_t hash = 0;
771         PyObject *key;
772
773         if (!PySet_Check(value)) {
774                 PyErr_Format(PyExc_TypeError,
775                              "%.200s expected a set, not %.200s",
776                              error_prefix, Py_TYPE(value)->tp_name);
777                 return -1;
778         }
779
780         *r_value = 0;
781
782         while (_PySet_NextEntry(value, &pos, &key, &hash)) {
783                 const char *param = _PyUnicode_AsString(key);
784
785                 if (param == NULL) {
786                         PyErr_Format(PyExc_TypeError,
787                                      "%.200s set must contain strings, not %.200s",
788                                      error_prefix, Py_TYPE(key)->tp_name);
789                         return -1;
790                 }
791
792                 if (PyC_FlagSet_ValueFromID(items, param, &ret, error_prefix) < 0) {
793                         return -1;
794                 }
795
796                 flag |= ret;
797         }
798
799         *r_value = flag;
800         return 0;
801 }
802
803 PyObject *PyC_FlagSet_FromBitfield(PyC_FlagSet *items, int flag)
804 {
805         PyObject *ret = PySet_New(NULL);
806         PyObject *pystr;
807
808         for ( ; items->identifier; items++) {
809                 if (items->value & flag) {
810                         pystr = PyUnicode_FromString(items->identifier);
811                         PySet_Add(ret, pystr);
812                         Py_DECREF(pystr);
813                 }
814         }
815
816         return ret;
817 }