[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [11005] branches/pyapi_devel/source/ blender: Solution for python referencing invalid ID pointers ( as discussed at the python meeting)
Campbell Barton
cbarton at metavr.com
Fri Jun 22 15:08:03 CEST 2007
Revision: 11005
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=11005
Author: campbellbarton
Date: 2007-06-22 15:08:03 +0200 (Fri, 22 Jun 2007)
Log Message:
-----------
Solution for python referencing invalid ID pointers (as discussed at the python meeting)
http://wiki.blender.org/index.php/Rewriting_the_2.4x_BPython_API#Managing_Pointers
Only work on text and scenes at the moment
Modified Paths:
--------------
branches/pyapi_devel/source/blender/blenkernel/intern/library.c
branches/pyapi_devel/source/blender/python/BPY_extern.h
branches/pyapi_devel/source/blender/python/BPY_interface.c
branches/pyapi_devel/source/blender/python/api2_2x/Scene.c
branches/pyapi_devel/source/blender/python/api2_2x/Text.c
branches/pyapi_devel/source/blender/python/api2_2x/layer_set.c
branches/pyapi_devel/source/blender/python/api2_2x/layer_set.h
Modified: branches/pyapi_devel/source/blender/blenkernel/intern/library.c
===================================================================
--- branches/pyapi_devel/source/blender/blenkernel/intern/library.c 2007-06-22 11:55:00 UTC (rev 11004)
+++ branches/pyapi_devel/source/blender/blenkernel/intern/library.c 2007-06-22 13:08:03 UTC (rev 11005)
@@ -114,6 +114,9 @@
#include "BPI_script.h"
+/* for maintaining the python id hash when removign data */
+#include "BPY_extern.h"
+
#define MAX_IDPUP 60 /* was 24 */
/* ************* general ************************ */
@@ -423,6 +426,9 @@
{
ID *id= idv;
+ /* invalidate the data if its in the python pool */
+ BPY_idhash_invalidate(id);
+
switch( GS(id->name) ) { /* GetShort from util.h */
case ID_SCE:
free_scene((Scene *)id);
Modified: branches/pyapi_devel/source/blender/python/BPY_extern.h
===================================================================
--- branches/pyapi_devel/source/blender/python/BPY_extern.h 2007-06-22 11:55:00 UTC (rev 11004)
+++ branches/pyapi_devel/source/blender/python/BPY_extern.h 2007-06-22 13:08:03 UTC (rev 11005)
@@ -96,6 +96,12 @@
void BPY_clear_script( struct Script *script );
void BPY_free_finished_script( struct Script *script );
+/* tell python were removing this ID so python can NULL the pointers */
+ void BPY_idhash_add(void * value);
+ void *BPY_idhash_get(ID *id);
+ void BPY_idhash_remove(ID *id);
+ void BPY_idhash_invalidate(ID *id);
+
/* void BPY_Err_Handle(struct Text *text); */
/* void BPY_clear_bad_scriptlink(struct ID *id, struct Text *byebye); */
/* void BPY_clear_bad_scriptlist(struct ListBase *, struct Text *byebye); */
Modified: branches/pyapi_devel/source/blender/python/BPY_interface.c
===================================================================
--- branches/pyapi_devel/source/blender/python/BPY_interface.c 2007-06-22 11:55:00 UTC (rev 11004)
+++ branches/pyapi_devel/source/blender/python/BPY_interface.c 2007-06-22 13:08:03 UTC (rev 11005)
@@ -36,6 +36,7 @@
#include "compile.h" /* for the PyCodeObject */
#include "eval.h" /* for PyEval_EvalCode */
#include "BLI_blenlib.h" /* for BLI_last_slash() */
+#include "BLI_ghash.h" /* for tracking removed data */
#include "BIF_interface.h" /* for pupmenu() */
#include "BIF_space.h"
#include "BIF_screen.h"
@@ -68,6 +69,10 @@
#include "api2_2x/Registry.h"
#include "api2_2x/bpy.h" /* for the new "bpy" module */
+#include "api2_2x/gen_library.h"
+#include "blendef.h"
+#include "BKE_utildefines.h"
+
/* for scriptlinks */
#include "DNA_lamp_types.h"
#include "DNA_camera_types.h"
@@ -75,6 +80,8 @@
#include "DNA_scene_types.h"
#include "DNA_material_types.h"
+#include "DNA_ID.h"
+
/* bpy_registryDict is declared in api2_2x/Registry.h and defined
* in api2_2x/Registry.c
* This Python dictionary will be used to store data that scripts
@@ -154,7 +161,79 @@
void BPY_Err_Handle( char *script_name );
PyObject *traceback_getFilename( PyObject * tb );
+
/****************************************************************************
+* Description: These functions deal with maintaining a python hash of ID
+* types that can be removed. This is important because when blender data is
+* removed, python needs to invalidate the BPy data by setting its ID pointer
+* to NULL, after this, using this data will raise an error.
+****************************************************************************/
+
+const GHash *bpy_idhash_text;
+const GHash *bpy_idhash_scene;
+const GHash *bpy_idhash_object;
+const GHash *bpy_idhash_group;
+
+static GHash * idhash__internal(ID *id)
+{
+ switch (GS(id->name)) {
+ case ID_TXT:
+ return bpy_idhash_text;
+ case ID_SCE:
+ return bpy_idhash_scene;
+ case ID_OB:
+ return bpy_idhash_object;
+ case ID_GR:
+ return bpy_idhash_group;
+ }
+ return NULL; /* WARNING - this will crash BLI_ghash_lookup */
+}
+
+/* Use so duplicate PyObjects are never created */
+void * BPY_idhash_get(ID *id)
+{
+ printf("getting hash\n");
+ return BLI_ghash_lookup(idhash__internal(id), id);
+}
+/* Use when python decref's the data
+ * no need to worry about a loose pointer because python
+ * isnt referencing any more */
+void BPY_idhash_remove(ID *id)
+{
+ GHash *hash = idhash__internal(id);
+ if (!hash) /* TODO - Dont allow invalid hashes at all*/
+ return;
+
+ BLI_ghash_remove(hash, id, NULL, NULL);
+}
+
+static void genlib_invalidate(void * genlib)
+{
+ ((BPy_GenericLib *)genlib)->id = NULL;
+}
+
+/* Use when removing the data data */
+void BPY_idhash_invalidate(ID *id)
+{
+ GHash *hash = idhash__internal(id);
+ if (!hash) /* TODO - Dont allow invalid hashes */
+ return;
+
+ BLI_ghash_remove(hash, id, NULL, genlib_invalidate);
+
+}
+
+/* Use when creating a new pyobject */
+void BPY_idhash_add(void *value)
+{
+ ID *id = ((BPy_GenericLib *)value)->id;
+ printf("adding hash\n");
+ BLI_ghash_insert(idhash__internal(id), (void *)id, (void *)value);
+}
+/* END OF BPY ID HASH */
+
+
+/****************************************************************************
* Description: This function will start the interpreter and load all modules
* as well as search for a python installation.
****************************************************************************/
@@ -214,7 +293,14 @@
//Look for a python installation
init_syspath( first_time ); /* not first_time: some msgs are suppressed */
-
+
+ // init hash
+ printf("initializing HASH\n");
+ bpy_idhash_text = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+ bpy_idhash_scene = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+ bpy_idhash_object = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+ bpy_idhash_group = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+
return;
}
@@ -249,6 +335,12 @@
/* a script might've opened a .blend file but didn't close it, so: */
EXPP_Library_Close( );
+ // free id hashes
+ BLI_ghash_free(bpy_idhash_text, NULL, NULL);
+ BLI_ghash_free(bpy_idhash_scene, NULL, NULL);
+ BLI_ghash_free(bpy_idhash_group, NULL, NULL);
+ BLI_ghash_free(bpy_idhash_object, NULL, NULL);
+
return;
}
Modified: branches/pyapi_devel/source/blender/python/api2_2x/Scene.c
===================================================================
--- branches/pyapi_devel/source/blender/python/api2_2x/Scene.c 2007-06-22 11:55:00 UTC (rev 11004)
+++ branches/pyapi_devel/source/blender/python/api2_2x/Scene.c 2007-06-22 13:08:03 UTC (rev 11005)
@@ -283,6 +283,20 @@
};
+/*
+ * Scene dealloc - free from memory and free from text pool
+ */
+static void Scene_dealloc( BPy_Scene * self )
+{
+ ID *id = (ID *)(self->scene);
+ if (id) {
+ BPY_idhash_remove(id);
+ }
+
+ PyObject_DEL( self );
+}
+
+
/*-----------------------BPy_Scene method def------------------------------*/
PyTypeObject Scene_Type = {
PyObject_HEAD_INIT( NULL )
@@ -291,7 +305,7 @@
sizeof( BPy_Scene ), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
- NULL, /* tp_dealloc */
+ ( destructor ) Scene_dealloc, /* tp_dealloc */
NULL, /* printfunc tp_print; */
NULL, /* getattrfunc tp_getattr; */
NULL, /* setattrfunc tp_setattr; */
@@ -395,7 +409,7 @@
static PyObject *Scene_repr( BPy_Scene * self )
{
if( !(self->scene) )
- return PyString_FromString( "[Scene - Removed]");
+ return PyString_FromString( "[Scene <deleted>]");
else
return PyString_FromFormat( "[Scene \"%s\"]",
self->scene->id.name + 2 );
@@ -406,6 +420,11 @@
{
BPy_Scene *pyscene;
+ /* REUSE EXISTING DATA FROM HASH */
+ pyscene = BPY_idhash_get((ID *)scene);
+ if (pyscene)
+ return EXPP_incr_ret((PyObject *)pyscene);
+
pyscene = ( BPy_Scene * ) PyObject_NEW( BPy_Scene, &Scene_Type );
if( !pyscene )
@@ -414,6 +433,8 @@
pyscene->scene = scene;
+ BPY_idhash_add((void *)pyscene);
+
return ( PyObject * ) pyscene;
}
Modified: branches/pyapi_devel/source/blender/python/api2_2x/Text.c
===================================================================
--- branches/pyapi_devel/source/blender/python/api2_2x/Text.c 2007-06-22 11:55:00 UTC (rev 11004)
+++ branches/pyapi_devel/source/blender/python/api2_2x/Text.c 2007-06-22 13:08:03 UTC (rev 11005)
@@ -119,7 +119,12 @@
PyObject *Text_CreatePyObject( Text * txt )
{
BPy_Text *pytxt;
-
+
+ /* REUSE EXISTING DATA FROM HASH */
+ pytxt = BPY_idhash_get((ID *)txt);
+ if (pytxt)
+ return EXPP_incr_ret((PyObject *)pytxt);
+
pytxt = ( BPy_Text * ) PyObject_NEW( BPy_Text, &Text_Type );
if( !pytxt )
@@ -128,6 +133,8 @@
pytxt->text = txt;
+ BPY_idhash_add((void *)pytxt);
+
return ( PyObject * ) pytxt;
}
@@ -298,7 +305,6 @@
/*****************************************************************************/
static PyGetSetDef BPy_Text_getseters[] = {
GENERIC_LIB_GETSETATTR,
- GENERIC_LIB_GETSETATTR_MATERIAL,
{"filename", (getter)Text_getFilename, (setter)NULL,
"text filename", NULL},
{"mode", (getter)Text_getMode, (setter)NULL,
@@ -308,6 +314,19 @@
{NULL,NULL,NULL,NULL,NULL} /* Sentinel */
};
+/*
+ * Text dealloc - free from memory and free from text pool
+ */
+static void Text_dealloc( BPy_Text * self )
+{
+ ID *id = (ID *)(self->text);
+ if (id) {
+ BPY_idhash_remove(id);
+ }
+
+ PyObject_DEL( self );
+}
+
/*****************************************************************************/
/* Python Text_Type structure definition: */
/*****************************************************************************/
@@ -318,7 +337,7 @@
sizeof( BPy_Text ), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
- NULL, /* tp_dealloc */
+ ( destructor ) Text_dealloc, /* tp_dealloc */
NULL, /* tp_print */
NULL, /* tp_getattr */
NULL, /* tp_setattr */
Modified: branches/pyapi_devel/source/blender/python/api2_2x/layer_set.c
===================================================================
--- branches/pyapi_devel/source/blender/python/api2_2x/layer_set.c 2007-06-22 11:55:00 UTC (rev 11004)
+++ branches/pyapi_devel/source/blender/python/api2_2x/layer_set.c 2007-06-22 13:08:03 UTC (rev 11005)
@@ -210,13 +210,13 @@
static int layer_from_iter__internal(PyObject *seq)
{
PyObject *item, *iter;
- int layer = 0, bit;
+ int layer = 0, bit;
- if (!PyIter_Check(seq))
+ iter = PyObject_GetIter(seq);
+
+ if (!iter)
return -1;
- iter = PyObject_GetIter(seq);
-
item = PyIter_Next(iter);
while (item) {
@@ -240,10 +240,27 @@
return layer; /* zero is ok here */
}
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list