[Python-Dev] Strange behaviour with PyEval_EvalCode

2007-05-13 Thread Joe Eagar
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.  Strangely this is only happening with internal 
blender types, yet try however I might I can't find any refcounting 
errors to account for this.  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). 
Also, when I printed the refcount of the garbage data, it was garbage as 
well (so the entire piece of memory is bad, not just the data portion).

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 debugging 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 );

[Python-Dev] Strange behaviour with PyEval_EvalCode

2007-05-13 Thread Joe Eagar
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.  Strangely this is only happening with internal
blender types, yet try however I might I can't find any refcounting
errors to account for this.   However adding an extra incref to a 
blender type creation function did appear to fix things and consistently 
return an object with reference count 1.

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).

Also, when I printed the refcount of the garbage data, it was garbage as
well (so the entire piece of memory is bad, not just the data portion). 
  Even more odd, the refcount of printing returned internal python types 
(which appears to otherwise work) steadily increase after each function 
call, despite being supposedly different objects.  I'm not decrefing the 
variable in my debug versions, but nonetheless I would expect each 
consecutive execution of the function to return new objects with 
reference 1.

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 debugging 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");

Re: [Python-Dev] Strange behaviour with PyEval_EvalCode

2007-05-13 Thread Joe Eagar
Joe Eagar wrote:
> 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.
>
>   
Eh sorry about the double post.

Joe
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] Strange behaviour with PyEval_EvalCode

2007-05-20 Thread Joe Eagar
[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] 

[Python-Dev] Strange behaviour with PyEval_EvalCode

2007-05-20 Thread Joe Eagar
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.b

[Python-Dev] Strange behaviour with PyEval_EvalCode

2007-05-20 Thread Joe Eagar
[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]