Blender V2.61 - r43446

bpy_interface.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * Contributor(s): Michel Selten, Willian P. Germano, Stephen Swaney,
00019  * Chris Keith, Chris Want, Ken Hughes, Campbell Barton
00020  *
00021  * ***** END GPL LICENSE BLOCK *****
00022  */
00023 
00033 /* grr, python redefines */
00034 #ifdef _POSIX_C_SOURCE
00035 #  undef _POSIX_C_SOURCE
00036 #endif
00037 
00038 #include <Python.h>
00039 
00040 #include "MEM_guardedalloc.h"
00041 
00042 #include "RNA_types.h"
00043 
00044 #include "bpy.h"
00045 #include "gpu.h"
00046 #include "bpy_rna.h"
00047 #include "bpy_util.h"
00048 #include "bpy_traceback.h"
00049 #include "bpy_intern_string.h"
00050 
00051 #include "DNA_space_types.h"
00052 #include "DNA_text_types.h"
00053 
00054 #include "BLI_path_util.h"
00055 #include "BLI_math_base.h"
00056 #include "BLI_string.h"
00057 #include "BLI_string_utf8.h"
00058 #include "BLI_utildefines.h"
00059 
00060 #include "BKE_context.h"
00061 #include "BKE_text.h"
00062 #include "BKE_main.h"
00063 #include "BKE_global.h" /* only for script checking */
00064 
00065 #include "CCL_api.h"
00066 
00067 #include "BPY_extern.h"
00068 
00069 #include "../generic/bpy_internal_import.h" // our own imports
00070 #include "../generic/py_capi_utils.h"
00071 
00072 /* inittab initialization functions */
00073 #include "../generic/bgl.h"
00074 #include "../generic/blf_py_api.h"
00075 #include "../mathutils/mathutils.h"
00076 
00077 /* for internal use, when starting and ending python scripts */
00078 
00079 /* incase a python script triggers another python call, stop bpy_context_clear from invalidating */
00080 static int py_call_level = 0;
00081 BPy_StructRNA *bpy_context_module = NULL; /* for fast access */
00082 
00083 // #define TIME_PY_RUN // simple python tests. prints on exit.
00084 
00085 #ifdef TIME_PY_RUN
00086 #include "PIL_time.h"
00087 static int      bpy_timer_count = 0;
00088 static double   bpy_timer; /* time since python starts */
00089 static double   bpy_timer_run; /* time for each python script run */
00090 static double   bpy_timer_run_tot; /* accumulate python runs */
00091 #endif
00092 
00093 /* use for updating while a python script runs - in case of file load */
00094 void bpy_context_update(bContext *C)
00095 {
00096     BPy_SetContext(C);
00097     bpy_import_main_set(CTX_data_main(C));
00098     BPY_modules_update(C); /* can give really bad results if this isnt here */
00099 }
00100 
00101 void bpy_context_set(bContext *C, PyGILState_STATE *gilstate)
00102 {
00103     py_call_level++;
00104 
00105     if (gilstate)
00106         *gilstate = PyGILState_Ensure();
00107 
00108     if (py_call_level == 1) {
00109         bpy_context_update(C);
00110 
00111 #ifdef TIME_PY_RUN
00112         if (bpy_timer_count == 0) {
00113             /* record time from the beginning */
00114             bpy_timer = PIL_check_seconds_timer();
00115             bpy_timer_run = bpy_timer_run_tot = 0.0;
00116         }
00117         bpy_timer_run = PIL_check_seconds_timer();
00118 
00119 
00120         bpy_timer_count++;
00121 #endif
00122     }
00123 }
00124 
00125 /* context should be used but not now because it causes some bugs */
00126 void bpy_context_clear(bContext *UNUSED(C), PyGILState_STATE *gilstate)
00127 {
00128     py_call_level--;
00129 
00130     if (gilstate)
00131         PyGILState_Release(*gilstate);
00132 
00133     if (py_call_level < 0) {
00134         fprintf(stderr, "ERROR: Python context internal state bug. this should not happen!\n");
00135     }
00136     else if (py_call_level == 0) {
00137         /* XXX - Calling classes currently wont store the context :\,
00138          * cant set NULL because of this. but this is very flakey still. */
00139 #if 0
00140         BPy_SetContext(NULL);
00141         bpy_import_main_set(NULL);
00142 #endif
00143 
00144 #ifdef TIME_PY_RUN
00145         bpy_timer_run_tot += PIL_check_seconds_timer() - bpy_timer_run;
00146         bpy_timer_count++;
00147 #endif
00148 
00149     }
00150 }
00151 
00152 void BPY_text_free_code(Text *text)
00153 {
00154     if (text->compiled) {
00155         Py_DECREF((PyObject *)text->compiled);
00156         text->compiled = NULL;
00157     }
00158 }
00159 
00160 void BPY_modules_update(bContext *C)
00161 {
00162 #if 0 // slow, this runs all the time poll, draw etc 100's of time a sec.
00163     PyObject *mod = PyImport_ImportModuleLevel("bpy", NULL, NULL, NULL, 0);
00164     PyModule_AddObject(mod, "data", BPY_rna_module());
00165     PyModule_AddObject(mod, "types", BPY_rna_types()); // atm this does not need updating
00166 #endif
00167 
00168     /* refreshes the main struct */
00169     BPY_update_rna_module();
00170     bpy_context_module->ptr.data = (void *)C;
00171 }
00172 
00173 void BPY_context_set(bContext *C)
00174 {
00175     BPy_SetContext(C);
00176 }
00177 
00178 /* defined in AUD_C-API.cpp */
00179 extern PyObject *AUD_initPython(void);
00180 
00181 #ifdef WITH_CYCLES
00182 /* defined in cycles module */
00183 static PyObject *CCL_initPython(void)
00184 {
00185     return (PyObject*)CCL_python_module_init();
00186 }
00187 #endif
00188 
00189 static struct _inittab bpy_internal_modules[] = {
00190     {(char *)"mathutils", PyInit_mathutils},
00191 //  {(char *)"mathutils.geometry", PyInit_mathutils_geometry},
00192 //  {(char *)"mathutils.noise", PyInit_mathutils_noise},
00193     {(char *)"bgl", BPyInit_bgl},
00194     {(char *)"blf", BPyInit_blf},
00195 #ifdef WITH_AUDASPACE
00196     {(char *)"aud", AUD_initPython},
00197 #endif
00198 #ifdef WITH_CYCLES
00199     {(char *)"_cycles", CCL_initPython},
00200 #endif
00201     {(char *)"gpu", GPU_initPython},
00202     {NULL, NULL}
00203 };
00204 
00205 /* call BPY_context_set first */
00206 void BPY_python_start(int argc, const char **argv)
00207 {
00208 #ifndef WITH_PYTHON_MODULE
00209     PyThreadState *py_tstate = NULL;
00210 
00211     /* not essential but nice to set our name */
00212     static wchar_t program_path_wchar[FILE_MAX]; /* python holds a reference */
00213     BLI_strncpy_wchar_from_utf8(program_path_wchar, BLI_program_path(), sizeof(program_path_wchar) / sizeof(wchar_t));
00214     Py_SetProgramName(program_path_wchar);
00215 
00216     /* must run before python initializes */
00217     PyImport_ExtendInittab(bpy_internal_modules);
00218 
00219     /* allow to use our own included python */
00220     PyC_SetHomePath(BLI_get_folder(BLENDER_SYSTEM_PYTHON, NULL));
00221 
00222     /* without this the sys.stdout may be set to 'ascii'
00223      * (it is on my system at least), where printing unicode values will raise
00224      * an error, this is highly annoying, another stumbling block for devs,
00225      * so use a more relaxed error handler and enforce utf-8 since the rest of
00226      * blender is utf-8 too - campbell */
00227     BLI_setenv("PYTHONIOENCODING", "utf-8:surrogateescape");
00228 
00229     /* Python 3.2 now looks for '2.xx/python/include/python3.2d/pyconfig.h' to
00230      * parse from the 'sysconfig' module which is used by 'site',
00231      * so for now disable site. alternatively we could copy the file. */
00232     Py_NoSiteFlag = 1;
00233 
00234     Py_Initialize();
00235 
00236     // PySys_SetArgv(argc, argv); // broken in py3, not a huge deal
00237     /* sigh, why do python guys not have a char** version anymore? :( */
00238     {
00239         int i;
00240         PyObject *py_argv = PyList_New(argc);
00241         for (i = 0; i < argc; i++) {
00242             /* should fix bug #20021 - utf path name problems, by replacing
00243              * PyUnicode_FromString, with this one */
00244             PyList_SET_ITEM(py_argv, i, PyC_UnicodeFromByte(argv[i]));
00245         }
00246 
00247         PySys_SetObject("argv", py_argv);
00248         Py_DECREF(py_argv);
00249     }
00250     
00251     /* Initialize thread support (also acquires lock) */
00252     PyEval_InitThreads();
00253 #else
00254     (void)argc;
00255     (void)argv;
00256 
00257     /* must run before python initializes */
00258     PyImport_ExtendInittab(bpy_internal_modules);
00259 #endif
00260 
00261     bpy_intern_string_init();
00262 
00263     /* bpy.* and lets us import it */
00264     BPy_init_modules();
00265 
00266     bpy_import_init(PyEval_GetBuiltins());
00267     
00268     pyrna_alloc_types();
00269 
00270     BPY_atexit_register(); /* this can init any time */
00271 
00272 #ifndef WITH_PYTHON_MODULE
00273     py_tstate = PyGILState_GetThisThreadState();
00274     PyEval_ReleaseThread(py_tstate);
00275 #endif
00276 }
00277 
00278 void BPY_python_end(void)
00279 {
00280     // fprintf(stderr, "Ending Python!\n");
00281 
00282     PyGILState_Ensure(); /* finalizing, no need to grab the state */
00283     
00284     // free other python data.
00285     pyrna_free_types();
00286 
00287     /* clear all python data from structs */
00288 
00289     bpy_intern_string_exit();
00290 
00291     BPY_atexit_unregister(); /* without this we get recursive calls to WM_exit */
00292 
00293     Py_Finalize();
00294     
00295 #ifdef TIME_PY_RUN
00296     // measure time since py started
00297     bpy_timer = PIL_check_seconds_timer() - bpy_timer;
00298 
00299     printf("*bpy stats* - ");
00300     printf("tot exec: %d,  ", bpy_timer_count);
00301     printf("tot run: %.4fsec,  ", bpy_timer_run_tot);
00302     if (bpy_timer_count > 0)
00303         printf("average run: %.6fsec,  ", (bpy_timer_run_tot/bpy_timer_count));
00304 
00305     if (bpy_timer > 0.0)
00306         printf("tot usage %.4f%%", (bpy_timer_run_tot/bpy_timer) * 100.0);
00307 
00308     printf("\n");
00309 
00310     // fprintf(stderr, "Ending Python Done!\n");
00311 
00312 #endif
00313 
00314 }
00315 
00316 static void python_script_error_jump_text(struct Text *text)
00317 {
00318     int lineno;
00319     int offset;
00320     python_script_error_jump(text->id.name + 2, &lineno, &offset);
00321     if (lineno != -1) {
00322         /* select the line with the error */
00323         txt_move_to(text, lineno - 1, INT_MAX, FALSE);
00324         txt_move_to(text, lineno - 1, offset, TRUE);
00325     }
00326 }
00327 
00328 /* super annoying, undo _PyModule_Clear(), bug [#23871] */
00329 #define PYMODULE_CLEAR_WORKAROUND
00330 
00331 #ifdef PYMODULE_CLEAR_WORKAROUND
00332 /* bad!, we should never do this, but currently only safe way I could find to keep namespace.
00333  * from being cleared. - campbell */
00334 typedef struct {
00335     PyObject_HEAD
00336     PyObject *md_dict;
00337     /* ommit other values, we only want the dict. */
00338 } PyModuleObject;
00339 #endif
00340 
00341 static int python_script_exec(bContext *C, const char *fn, struct Text *text,
00342                               struct ReportList *reports, const short do_jump)
00343 {
00344     PyObject *main_mod = NULL;
00345     PyObject *py_dict = NULL, *py_result = NULL;
00346     PyGILState_STATE gilstate;
00347 
00348     BLI_assert(fn || text);
00349 
00350     if (fn == NULL && text == NULL) {
00351         return 0;
00352     }
00353 
00354     bpy_context_set(C, &gilstate);
00355 
00356     PyC_MainModule_Backup(&main_mod);
00357 
00358     if (text) {
00359         char fn_dummy[FILE_MAXDIR];
00360         bpy_text_filename_get(fn_dummy, sizeof(fn_dummy), text);
00361 
00362         if (text->compiled == NULL) {   /* if it wasn't already compiled, do it now */
00363             char *buf = txt_to_buf(text);
00364 
00365             text->compiled = Py_CompileString(buf, fn_dummy, Py_file_input);
00366 
00367             MEM_freeN(buf);
00368 
00369             if (PyErr_Occurred()) {
00370                 if (do_jump) {
00371                     python_script_error_jump_text(text);
00372                 }
00373                 BPY_text_free_code(text);
00374             }
00375         }
00376 
00377         if (text->compiled) {
00378             py_dict = PyC_DefaultNameSpace(fn_dummy);
00379             py_result =  PyEval_EvalCode(text->compiled, py_dict, py_dict);
00380         }
00381 
00382     }
00383     else {
00384         FILE *fp = fopen(fn, "r");
00385 
00386         if (fp) {
00387             py_dict = PyC_DefaultNameSpace(fn);
00388 
00389 #ifdef _WIN32
00390             /* Previously we used PyRun_File to run directly the code on a FILE
00391              * object, but as written in the Python/C API Ref Manual, chapter 2,
00392              * 'FILE structs for different C libraries can be different and
00393              * incompatible'.
00394              * So now we load the script file data to a buffer */
00395             {
00396                 char *pystring;
00397 
00398                 fclose(fp);
00399 
00400                 pystring = MEM_mallocN(strlen(fn) + 32, "pystring");
00401                 pystring[0] = '\0';
00402                 sprintf(pystring, "exec(open(r'%s').read())", fn);
00403                 py_result = PyRun_String(pystring, Py_file_input, py_dict, py_dict);
00404                 MEM_freeN(pystring);
00405             }
00406 #else
00407             py_result = PyRun_File(fp, fn, Py_file_input, py_dict, py_dict);
00408             fclose(fp);
00409 #endif
00410         }
00411         else {
00412             PyErr_Format(PyExc_IOError,
00413                          "Python file \"%s\" could not be opened: %s",
00414                          fn, strerror(errno));
00415             py_result = NULL;
00416         }
00417     }
00418 
00419     if (!py_result) {
00420         if (text) {
00421             if (do_jump) {
00422                 python_script_error_jump_text(text);
00423             }
00424         }
00425         BPy_errors_to_report(reports);
00426     }
00427     else {
00428         Py_DECREF(py_result);
00429     }
00430 
00431     if (py_dict) {
00432 #ifdef PYMODULE_CLEAR_WORKAROUND
00433         PyModuleObject *mmod = (PyModuleObject *)PyDict_GetItemString(PyThreadState_GET()->interp->modules, "__main__");
00434         PyObject *dict_back = mmod->md_dict;
00435         /* freeing the module will clear the namespace,
00436          * gives problems running classes defined in this namespace being used later. */
00437         mmod->md_dict = NULL;
00438         Py_DECREF(dict_back);
00439 #endif
00440 
00441 #undef PYMODULE_CLEAR_WORKAROUND
00442     }
00443 
00444     PyC_MainModule_Restore(main_mod);
00445 
00446     bpy_context_clear(C, &gilstate);
00447 
00448     return (py_result != NULL);
00449 }
00450 
00451 /* Can run a file or text block */
00452 int BPY_filepath_exec(bContext *C, const char *filepath, struct ReportList *reports)
00453 {
00454     return python_script_exec(C, filepath, NULL, reports, FALSE);
00455 }
00456 
00457 
00458 int BPY_text_exec(bContext *C, struct Text *text, struct ReportList *reports, const short do_jump)
00459 {
00460     return python_script_exec(C, NULL, text, reports, do_jump);
00461 }
00462 
00463 void BPY_DECREF(void *pyob_ptr)
00464 {
00465     PyGILState_STATE gilstate = PyGILState_Ensure();
00466     Py_DECREF((PyObject *)pyob_ptr);
00467     PyGILState_Release(gilstate);
00468 }
00469 
00470 /* return -1 on error, else 0 */
00471 int BPY_button_exec(bContext *C, const char *expr, double *value, const short verbose)
00472 {
00473     PyGILState_STATE gilstate;
00474     PyObject *py_dict, *mod, *retval;
00475     int error_ret = 0;
00476     PyObject *main_mod = NULL;
00477     
00478     if (!value || !expr) return -1;
00479 
00480     if (expr[0] == '\0') {
00481         *value = 0.0;
00482         return error_ret;
00483     }
00484 
00485     bpy_context_set(C, &gilstate);
00486 
00487     PyC_MainModule_Backup(&main_mod);
00488 
00489     py_dict = PyC_DefaultNameSpace("<blender button>");
00490 
00491     mod = PyImport_ImportModule("math");
00492     if (mod) {
00493         PyDict_Merge(py_dict, PyModule_GetDict(mod), 0); /* 0 - dont overwrite existing values */
00494         Py_DECREF(mod);
00495     }
00496     else { /* highly unlikely but possibly */
00497         PyErr_Print();
00498         PyErr_Clear();
00499     }
00500     
00501     retval = PyRun_String(expr, Py_eval_input, py_dict, py_dict);
00502     
00503     if (retval == NULL) {
00504         error_ret = -1;
00505     }
00506     else {
00507         double val;
00508 
00509         if (PyTuple_Check(retval)) {
00510             /* Users my have typed in 10km, 2m
00511              * add up all values */
00512             int i;
00513             val = 0.0;
00514 
00515             for (i = 0; i < PyTuple_GET_SIZE(retval); i++) {
00516                 val += PyFloat_AsDouble(PyTuple_GET_ITEM(retval, i));
00517             }
00518         }
00519         else {
00520             val = PyFloat_AsDouble(retval);
00521         }
00522         Py_DECREF(retval);
00523         
00524         if (val == -1 && PyErr_Occurred()) {
00525             error_ret = -1;
00526         }
00527         else if (!finite(val)) {
00528             *value = 0.0;
00529         }
00530         else {
00531             *value = val;
00532         }
00533     }
00534     
00535     if (error_ret) {
00536         if (verbose) {
00537             BPy_errors_to_report(CTX_wm_reports(C));
00538         }
00539         else {
00540             PyErr_Clear();
00541         }
00542     }
00543 
00544     PyC_MainModule_Backup(&main_mod);
00545     
00546     bpy_context_clear(C, &gilstate);
00547     
00548     return error_ret;
00549 }
00550 
00551 int BPY_string_exec(bContext *C, const char *expr)
00552 {
00553     PyGILState_STATE gilstate;
00554     PyObject *main_mod = NULL;
00555     PyObject *py_dict, *retval;
00556     int error_ret = 0;
00557     Main *bmain_back; /* XXX, quick fix for release (Copy Settings crash), needs further investigation */
00558 
00559     if (!expr) return -1;
00560 
00561     if (expr[0] == '\0') {
00562         return error_ret;
00563     }
00564 
00565     bpy_context_set(C, &gilstate);
00566 
00567     PyC_MainModule_Backup(&main_mod);
00568 
00569     py_dict = PyC_DefaultNameSpace("<blender string>");
00570 
00571     bmain_back = bpy_import_main_get();
00572     bpy_import_main_set(CTX_data_main(C));
00573 
00574     retval = PyRun_String(expr, Py_eval_input, py_dict, py_dict);
00575 
00576     bpy_import_main_set(bmain_back);
00577 
00578     if (retval == NULL) {
00579         error_ret = -1;
00580 
00581         BPy_errors_to_report(CTX_wm_reports(C));
00582     }
00583     else {
00584         Py_DECREF(retval);
00585     }
00586 
00587     PyC_MainModule_Restore(main_mod);
00588 
00589     bpy_context_clear(C, &gilstate);
00590     
00591     return error_ret;
00592 }
00593 
00594 
00595 void BPY_modules_load_user(bContext *C)
00596 {
00597     PyGILState_STATE gilstate;
00598     Main *bmain = CTX_data_main(C);
00599     Text *text;
00600 
00601     /* can happen on file load */
00602     if (bmain == NULL)
00603         return;
00604 
00605     /* update pointers since this can run from a nested script
00606      * on file load */
00607     if (py_call_level) {
00608         bpy_context_update(C);
00609     }
00610 
00611     bpy_context_set(C, &gilstate);
00612 
00613     for (text = CTX_data_main(C)->text.first; text; text = text->id.next) {
00614         if (text->flags & TXT_ISSCRIPT && BLI_testextensie(text->id.name + 2, ".py")) {
00615             if (!(G.f & G_SCRIPT_AUTOEXEC)) {
00616                 printf("scripts disabled for \"%s\", skipping '%s'\n", bmain->name, text->id.name + 2);
00617             }
00618             else {
00619                 PyObject *module = bpy_text_import(text);
00620 
00621                 if (module == NULL) {
00622                     PyErr_Print();
00623                     PyErr_Clear();
00624                 }
00625                 else {
00626                     Py_DECREF(module);
00627                 }
00628             }
00629         }
00630     }
00631     bpy_context_clear(C, &gilstate);
00632 }
00633 
00634 int BPY_context_member_get(bContext *C, const char *member, bContextDataResult *result)
00635 {
00636     PyObject *pyctx = (PyObject *)CTX_py_dict_get(C);
00637     PyObject *item = PyDict_GetItemString(pyctx, member);
00638     PointerRNA *ptr = NULL;
00639     int done = 0;
00640 
00641     if (item == NULL) {
00642         /* pass */
00643     }
00644     else if (item == Py_None) {
00645         /* pass */
00646     }
00647     else if (BPy_StructRNA_Check(item)) {
00648         ptr = &(((BPy_StructRNA *)item)->ptr);
00649 
00650         //result->ptr = ((BPy_StructRNA *)item)->ptr;
00651         CTX_data_pointer_set(result, ptr->id.data, ptr->type, ptr->data);
00652         done = 1;
00653     }
00654     else if (PySequence_Check(item)) {
00655         PyObject *seq_fast = PySequence_Fast(item, "bpy_context_get sequence conversion");
00656         if (seq_fast == NULL) {
00657             PyErr_Print();
00658             PyErr_Clear();
00659         }
00660         else {
00661             int len = PySequence_Fast_GET_SIZE(seq_fast);
00662             int i;
00663             for (i = 0; i < len; i++) {
00664                 PyObject *list_item = PySequence_Fast_GET_ITEM(seq_fast, i);
00665 
00666                 if (BPy_StructRNA_Check(list_item)) {
00667                     /*
00668                     CollectionPointerLink *link = MEM_callocN(sizeof(CollectionPointerLink), "bpy_context_get");
00669                     link->ptr = ((BPy_StructRNA *)item)->ptr;
00670                     BLI_addtail(&result->list, link);
00671                     */
00672                     ptr = &(((BPy_StructRNA *)list_item)->ptr);
00673                     CTX_data_list_add(result, ptr->id.data, ptr->type, ptr->data);
00674                 }
00675                 else {
00676                     printf("List item not a valid type\n");
00677                 }
00678 
00679             }
00680             Py_DECREF(seq_fast);
00681 
00682             done = 1;
00683         }
00684     }
00685 
00686     if (done == 0) {
00687         if (item)   printf("PyContext '%s' not a valid type\n", member);
00688         else        printf("PyContext '%s' not found\n", member);
00689     }
00690     else {
00691         if (G.f & G_DEBUG) {
00692             printf("PyContext '%s' found\n", member);
00693         }
00694     }
00695 
00696     return done;
00697 }
00698 
00699 
00700 #ifdef WITH_PYTHON_MODULE
00701 #include "BLI_fileops.h"
00702 /* TODO, reloading the module isnt functional at the moment. */
00703 
00704 static void bpy_module_free(void *mod);
00705 extern int main_python_enter(int argc, const char **argv);
00706 extern void main_python_exit(void);
00707 static struct PyModuleDef bpy_proxy_def = {
00708     PyModuleDef_HEAD_INIT,
00709     "bpy",  /* m_name */
00710     NULL,  /* m_doc */
00711     0,  /* m_size */
00712     NULL,  /* m_methods */
00713     NULL,  /* m_reload */
00714     NULL,  /* m_traverse */
00715     NULL,  /* m_clear */
00716     bpy_module_free,  /* m_free */
00717 };
00718 
00719 typedef struct {
00720     PyObject_HEAD
00721     /* Type-specific fields go here. */
00722     PyObject *mod;
00723 } dealloc_obj;
00724 
00725 /* call once __file__ is set */
00726 void bpy_module_delay_init(PyObject *bpy_proxy)
00727 {
00728     const int argc = 1;
00729     const char *argv[2];
00730 
00731     /* updating the module dict below will loose the reference to __file__ */
00732     PyObject *filename_obj = PyModule_GetFilenameObject(bpy_proxy);
00733 
00734     const char *filename_rel = _PyUnicode_AsString(filename_obj); /* can be relative */
00735     char filename_abs[1024];
00736 
00737     BLI_strncpy(filename_abs, filename_rel, sizeof(filename_abs));
00738     BLI_path_cwd(filename_abs);
00739 
00740     argv[0] = filename_abs;
00741     argv[1] = NULL;
00742     
00743     // printf("module found %s\n", argv[0]);
00744 
00745     main_python_enter(argc, argv);
00746 
00747     /* initialized in BPy_init_modules() */
00748     PyDict_Update(PyModule_GetDict(bpy_proxy), PyModule_GetDict(bpy_package_py));
00749 }
00750 
00751 static void dealloc_obj_dealloc(PyObject *self);
00752 
00753 static PyTypeObject dealloc_obj_Type = {{{0}}};
00754 
00755 /* use our own dealloc so we can free a property if we use one */
00756 static void dealloc_obj_dealloc(PyObject *self)
00757 {
00758     bpy_module_delay_init(((dealloc_obj *)self)->mod);
00759 
00760     /* Note, for subclassed PyObjects we cant just call PyObject_DEL() directly or it will crash */
00761     dealloc_obj_Type.tp_free(self);
00762 }
00763 
00764 PyMODINIT_FUNC
00765 PyInit_bpy(void)
00766 {
00767     PyObject *bpy_proxy = PyModule_Create(&bpy_proxy_def);
00768     
00769     /* Problem:
00770      * 1) this init function is expected to have a private member defined - 'md_def'
00771      *    but this is only set for C defined modules (not py packages)
00772      *    so we cant return 'bpy_package_py' as is.
00773      *
00774      * 2) there is a 'bpy' C module for python to load which is basically all of blender,
00775      *    and there is scripts/bpy/__init__.py, 
00776      *    we may end up having to rename this module so there is no naming conflict here eg:
00777      *    'from blender import bpy'
00778      *
00779      * 3) we dont know the filename at this point, workaround by assigning a dummy value
00780      *    which calls back when its freed so the real loading can take place.
00781      */
00782 
00783     /* assign an object which is freed after __file__ is assigned */
00784     dealloc_obj *dob;
00785     
00786     /* assign dummy type */
00787     dealloc_obj_Type.tp_name = "dealloc_obj";
00788     dealloc_obj_Type.tp_basicsize = sizeof(dealloc_obj);
00789     dealloc_obj_Type.tp_dealloc = dealloc_obj_dealloc;
00790     dealloc_obj_Type.tp_flags = Py_TPFLAGS_DEFAULT;
00791     
00792     if (PyType_Ready(&dealloc_obj_Type) < 0)
00793         return NULL;
00794 
00795     dob = (dealloc_obj *) dealloc_obj_Type.tp_alloc(&dealloc_obj_Type, 0);
00796     dob->mod = bpy_proxy; /* borrow */
00797     PyModule_AddObject(bpy_proxy, "__file__", (PyObject *)dob); /* borrow */
00798 
00799     return bpy_proxy;
00800 }
00801 
00802 static void bpy_module_free(void *UNUSED(mod))
00803 {
00804     main_python_exit();
00805 }
00806 
00807 #endif