Blender V2.61 - r43446

bpy_interface_atexit.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): Campbell Barton
00019  *
00020  * ***** END GPL LICENSE BLOCK *****
00021  */
00022 
00032 #include <Python.h>
00033 
00034 #include "bpy_util.h"
00035 
00036 #include "WM_api.h"
00037 
00038 #include "BLI_utildefines.h"
00039 
00040 static PyObject *bpy_atexit(PyObject *UNUSED(self), PyObject *UNUSED(args), PyObject *UNUSED(kw))
00041 {
00042     /* close down enough of blender at least not to crash */
00043     struct bContext *C = BPy_GetContext();
00044 
00045     WM_exit_ext(C, 0);
00046 
00047     Py_RETURN_NONE;
00048 }
00049 
00050 static PyMethodDef meth_bpy_atexit = {"bpy_atexit", (PyCFunction)bpy_atexit, METH_NOARGS, NULL};
00051 static PyObject *func_bpy_atregister = NULL; /* borrowed referebce, atexit holds */
00052 
00053 static void atexit_func_call(const char *func_name, PyObject *atexit_func_arg)
00054 {
00055     /* note - no error checking, if any of these fail we'll get a crash
00056      * this is intended, but if its problematic it could be changed
00057      * - campbell */
00058 
00059     PyObject *atexit_mod = PyImport_ImportModuleLevel((char *)"atexit", NULL, NULL, NULL, 0);
00060     PyObject *atexit_func = PyObject_GetAttrString(atexit_mod, func_name);
00061     PyObject *args = PyTuple_New(1);
00062     PyObject *ret;
00063 
00064     PyTuple_SET_ITEM(args, 0, atexit_func_arg);
00065     Py_INCREF(atexit_func_arg); /* only incref so we dont dec'ref along with 'args' */
00066 
00067     ret = PyObject_CallObject(atexit_func, args);
00068 
00069     Py_DECREF(atexit_mod);
00070     Py_DECREF(atexit_func);
00071     Py_DECREF(args);
00072 
00073     if (ret) {
00074         Py_DECREF(ret);
00075     }
00076     else { /* should never happen */
00077         PyErr_Print();
00078     }
00079 }
00080 
00081 void BPY_atexit_register(void)
00082 {
00083     /* atexit module owns this new function reference */
00084     BLI_assert(func_bpy_atregister == NULL);
00085 
00086     func_bpy_atregister = (PyObject *)PyCFunction_New(&meth_bpy_atexit, NULL);
00087     atexit_func_call("register", func_bpy_atregister);
00088 }
00089 
00090 void BPY_atexit_unregister(void)
00091 {
00092     BLI_assert(func_bpy_atregister != NULL);
00093 
00094     atexit_func_call("unregister", func_bpy_atregister);
00095     func_bpy_atregister = NULL; /* don't really need to set but just incase */
00096 }