[Python-Dev] Strange behaviour with PyEval_EvalCode (original) (raw)
Joe Eagar joeedh at gmail.com
Thu May 10 13:27:38 CEST 2007
- Previous message: [Python-Dev] Strange behaviour with PyEval_EvalCode
- Next message: [Python-Dev] Official version support statement
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
[I'm re-sending this message cause it might've gotten lost; sorry if it ends up posting twice] Hi I'm getting extremely odd behavior. First of all, why isn't PyEval_EvalCode documented anywhere? Anyway, I'm working on blender's python integration (it embeds python, as opposed to python embedding it). I have a function that executes a string buffer of python code, fetches a function from its global dictionary then calls it.
When the function code returns a local variable, PyObject_Call() appears to be returning garbage. The initial implementation used the same dictionary for the global and local dicts. I tried using separate dicts, but then the function wasn't being called at all (or at least I tested it by putting a "print "bleh"" in there, and it didn't work).
I've tested with both python 2.4 and 2.5. Mostly with 2.4. This bug may be cropping up in other experimental blender python code as well.
Here's the code in the string buffer: #BPYCONSTRAINT from Blender import * from Blender.Mathutils import * print "d" def doConstraint(inmat, tarmat, prop): a = Matrix() a.identity() a = a * TranslationMatrix(Vector(0, 0, 0)) print "t" a = tarmat return inmat
print doConstraint(Matrix(), Matrix(), 0)
Here's the code that executes the string buffer:
PyObject *RunPython2( Text * text, PyObject * globaldict, PyObject *localdict ) { char *buf = NULL;
/* The script text is compiled to Python bytecode and saved at text->compiled
to speed-up execution if the user executes the script multiple times */
if( !text->compiled ) { // if it wasn't already compiled, do it now buf = txt_to_buf( text ); text->compiled = Py_CompileString( buf, GetName( text ), Py_file_input ); MEM_freeN( buf ); if( PyErr_Occurred( ) ) { BPY_free_compiled_text( text ); return NULL; } } return PyEval_EvalCode( text->compiled, globaldict, localdict );
}
. . .and heres the (rather long, and somewhat in a working state) function that calls the function in the script's global dictionary:
void BPY_pyconstraint_eval(bPythonConstraint *con, float obmat[][4], short ownertype, void *ownerdata, float targetmat[][4]) { PyObject *srcmat, *tarmat, *idprop; PyObject *globals, *locals; PyObject *gkey, *gval; PyObject *retval; MatrixObject *retmat; Py_ssize_t ppos = 0; int row, col;
if ( !con->text ) return;
globals = CreateGlobalDictionary();
srcmat = newMatrixObject( (float*)obmat, 4, 4, Py_NEW );
tarmat = newMatrixObject( (float*)targetmat, 4, 4, Py_NEW );
idprop = BPy_Wrap_IDProperty( NULL, &con->prop, NULL);
/* since I can't remember what the armature weakrefs do, I'll just leave this here commented out. Since this function was based on pydrivers. if( !setup_armature_weakrefs()){ fprintf( stderr, "Oops - weakref dict setup\n"); return result; } */ retval = RunPython2( con->text, globals, globals);
if (retval) {Py_XDECREF( retval );}
if ( retval == NULL ) {
BPY_Err_Handle(con->text->id.name);
ReleaseGlobalDictionary( globals );
/*free temp objects*/
Py_XDECREF( idprop );
Py_XDECREF( srcmat );
Py_XDECREF( tarmat );
return;
}
/*Now for the fun part! Try and find the functions we need.*/
while ( PyDict_Next(globals, &ppos, &gkey, &gval) ) {
if ( PyString_Check(gkey) && strcmp(PyString_AsString(gkey),
"doConstraint")==0 ) { if (PyFunction_Check(gval) ) { retval = PyObject_CallObject(gval, Py_BuildValue("OOO", srcmat, tarmat, idprop)); Py_XDECREF( retval ); } else { printf("ERROR: doConstraint is supposed to be a function!\n"); } break; } }
if (!retval) {
BPY_Err_Handle(con->text->id.name);
/*free temp objects*/
ReleaseGlobalDictionary( globals );
Py_XDECREF( idprop );
Py_XDECREF( srcmat );
Py_XDECREF( tarmat );
return;
}
if (!PyObject_TypeCheck(retval, &matrix_Type)) {
printf("Error in pyconstraint: Wrong return type for a
pyconstraint!\n"); ReleaseGlobalDictionary( globals );
Py_XDECREF( idprop );
Py_XDECREF( srcmat );
Py_XDECREF( tarmat );
Py_XDECREF( retval );
return;
}
retmat = (MatrixObject*) retval;
if (retmat->rowSize != 4 || retmat->colSize != 4) {
printf("Error in pyconstraint: Matrix is the wrong size!\n");
ReleaseGlobalDictionary( globals );
Py_XDECREF( idprop );
Py_XDECREF( srcmat );
Py_XDECREF( tarmat );
Py_XDECREF( retval );
return;
}
//this is the reverse of code taken from newMatrix().
for(row = 0; row < 4; row++) {
for(col = 0; col < 4; col++) {
if (retmat->wrapped) obmat[row][col] =
retmat->data.blend_data[row4+col]; //[row][col]; else obmat[row][col] = retmat->data.py_data[row4+col]; //[row][col];
}
}
/*clear globals*/
//ReleaseGlobalDictionary( globals );
/*free temp objects*/
//Py_XDECREF( idprop );
//Py_XDECREF( srcmat );
//Py_XDECREF( tarmat );
//Py_XDECREF( retval );
//PyDict_Clear(locals);
//Py_XDECREF(locals);
}
Joe
- Previous message: [Python-Dev] Strange behaviour with PyEval_EvalCode
- Next message: [Python-Dev] Official version support statement
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]