Extension problem: Is my type object duplicated?
Jonas Bjering
jonas at kryfos.com
Wed Jun 11 05:39:25 EDT 2003
Hello,
I am writing a Python Extension in C and have encountered a problem,
explicitly created (Explicit as in v = Vector(1, 2, 3)) instances of
my object has a ob_type pointer that refers to a different address
than the address of my static type object. How can this be?
It create trouble for me when objects I create as a result of
operations have ob_type set to the address of my static type object
(as I expected all objects of my type would have) and when I compare
ob_type to check they are of the same type it fails.
Specifically in my case the symptom is I get v + v working while v + v
+ v fails as the result of the first addition has a different ob_type
ptr from v.
I include my type definition and the relevant functions below. If
someone can tell me what I do wrong I would be very appreciated.
Thank you
Jonas Bjering
header..
#ifndef _PYVECTOR_H_
#define _PYVECTOR_H_
#include "Python.h"
#include "vector.h"
typedef struct
{
PyObject_HEAD
CVector3<float> _vector;
} CVectorObject;
int InitVector( CVectorObject* self, PyObject* args, PyObject* kwds );
PyObject* AddVector( CVectorObject* self, PyObject* args );
int CoerceVector( PyObject ** o1, PyObject ** o2 );
PyObject* VectorRichCompare(PyObject* o1, PyObject* o2, int cmpOp);
PyObject* VectorRepr( CVectorObject* self );
static PyMethodDef vectorMethods[] =
{
{NULL, NULL, NULL, NULL}
};
static PyNumberMethods vectorAsNumeric = {
(binaryfunc) AddVector, // binaryfunc nb_add;
0, // binaryfunc nb_subtract;
0, // binaryfunc nb_multiply;
0, // binaryfunc nb_divide;
0, // binaryfunc nb_remainder;
0, // binaryfunc nb_divmod;
0, // ternaryfunc nb_power;
0, // unaryfunc nb_negative;
0, // unaryfunc nb_positive;
0, // unaryfunc nb_absolute;
0, // inquiry nb_nonzero;
0, // unaryfunc nb_invert;
0, // binaryfunc nb_lshift;
0, // binaryfunc nb_rshift;
0, // binaryfunc nb_and;
0, // binaryfunc nb_xor;
0, // binaryfunc nb_or;
(coercion) CoerceVector, // coercion nb_coerce;
0, // unaryfunc nb_int;
0, // unaryfunc nb_long;
0, // unaryfunc nb_float;
0, // unaryfunc nb_oct;
0, // unaryfunc nb_hex;
0, // binaryfunc nb_inplace_add;
0, // binaryfunc nb_inplace_subtract;
0, // binaryfunc nb_inplace_multiply;
0, // binaryfunc nb_inplace_divide;
0, // binaryfunc nb_inplace_remainder;
0, // ternaryfunc nb_inplace_power;
0, // binaryfunc nb_inplace_lshift;
0, // binaryfunc nb_inplace_rshift;
0, // binaryfunc nb_inplace_and;
0, // binaryfunc nb_inplace_xor;
0, // binaryfunc nb_inplace_or;
0, // binaryfunc nb_floor_divide;
0, // binaryfunc nb_true_divide;
0, // binaryfunc nb_inplace_floor_divide;
0 // binaryfunc nb_inplace_true_divide;
};
// {"__add__", (PyCFunction) AddVector, METH_VARARGS, "Adds a vector
to another and returns the result."},
static PyTypeObject vectorType = {
PyObject_HEAD_INIT(NULL)
0,
"pyclausewitz.Vector",
sizeof(CVectorObject),
0,
(destructor) PyObject_Del, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
(reprfunc) VectorRepr, /* tp_repr */
&vectorAsNumeric, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
VectorRichCompare, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
vectorMethods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc) InitVector, /* tp_init */
0, /* tp_alloc */
PyType_GenericNew, /* tp_new */
0, //freefunc tp_free; /* Low-level free-memory routine */
0, //inquiry tp_is_gc; /* For PyObject_IS_GC */
0, //PyObject *tp_bases;
0, //PyObject *tp_mro; /* method resolution order */
0, //PyObject *tp_cache;
0, //PyObject *tp_subclasses;
0, //PyObject *tp_weaklist;
0, //destructor tp_del;
#ifdef COUNT_ALLOCS
///* these must be last and never explicitly initialized
*/
0, //int tp_allocs;
0, //int tp_frees;
0, //int tp_maxalloc;
0, //struct _typeobject *tp_next;
#endif
};
#endif
and the implementation...
#include "pyvector.h"
#include "text.h"
int InitVector( CVectorObject* self, PyObject* args, PyObject*
keywordvalues )
{
float x;
float y;
float z;
static char *keywords[] = {"x", "y", "z", NULL};
if( !PyArg_ParseTupleAndKeywords(args, keywordvalues, "fff",
keywords,
&x, &y, &z) )
return -1;
self->_vector = CVector3<float>( x, y, z );
return 0;
}
PyObject* VectorRichCompare(PyObject* o1, PyObject* o2, int cmpOp)
{
if( !( o1->ob_type == &vectorType && o1->ob_type == &vectorType) )
{
CString errorMsg("Cannot compare " + CString( o1->ob_type->tp_name )
+ " to " + CString( o2->ob_type->tp_name ));
PyErr_SetString( PyExc_NotImplementedError, errorMsg.GetCharPtr() );
return NULL;
}
CVectorObject* v1 = reinterpret_cast<CVectorObject*>( o1 );
CVectorObject* v2 = reinterpret_cast<CVectorObject*>( o2 );
if( cmpOp == Py_EQ )
{
if( v1->_vector == v2->_vector )
{
Py_INCREF( Py_True );
return Py_True;
}
else
{
Py_INCREF( Py_False );
return Py_False;
}
}
else if( cmpOp == Py_NE )
{
if( v1->_vector != v2->_vector )
{
Py_INCREF( Py_True );
return Py_True;
}
else
{
Py_INCREF( Py_False );
return Py_False;
}
}
else
{
CString errorMsg("Operation not supported");
PyErr_SetString( PyExc_NotImplementedError, errorMsg.GetCharPtr() );
return NULL;
}
}
int CoerceVector( PyObject ** o1, PyObject ** o2 )
{
if( (*o1)->ob_type == &vectorType && (*o1)->ob_type == &vectorType )
{
Py_INCREF( *o1 );
Py_INCREF( *o2 );
return 0;
}
else
return 1;
}
PyObject* AddVector( CVectorObject* self, PyObject* other )
{
if( other->ob_type != self->ob_type )
{
CString errorMsg("Cannot convert " + CString(
other->ob_type->tp_name ) + " to " + CString( self->ob_type->tp_name
));
PyErr_SetString( PyExc_TypeError, errorMsg.GetCharPtr() );
return NULL;
}
CVectorObject* otherAsVector = reinterpret_cast<CVectorObject*>(
other );
CVectorObject* result = PyObject_New( CVectorObject, &vectorType );
result->_vector = self->_vector + otherAsVector->_vector;
return reinterpret_cast<PyObject*>( result );
}
PyObject* VectorRepr( CVectorObject* self )
{
CString result( "Vector(" );
result = result + CString(self->_vector.x) + ", " +
CString(self->_vector.y) + ", " + CString(self->_vector.z) + ")";
return Py_BuildValue( "s", result.GetCharPtr() );
}
More information about the Python-list
mailing list