[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