New Type in Extension Module Not Accessing PyNumberMethods???

doug doug_bartholomew99 at yahoo.com
Wed Aug 8 22:42:25 EDT 2001


im trying to write a python extension type which i am basically
modeling on xxmodule.c that comes with the source.  however, for the
life of me, i cannot get the numeric operations to work (just simple
addition and subtraction here) and i cannot see what im doing wrong. 
Isnt the following what one has to do to get numeric operations???

***BEGIN CODE SNIPPET***

static PyObject*
MyObject_add(MyObject *Self, PyObject *Arg)
{
   long c_long; 
   MyObject* rv;
   if ( !PyInt_Check(Arg) )
   {
      PyErr_SetString(PyExc_TypeError, "Should add a number to
MyObject");
      return NULL;
   }
   c_long = PyInt_AS_LONG(Arg);
   rv = newMyObject(Self->my_num + c_long);
   if ( rv == NULL )
       return NULL;
   return (PyObject *)rv;
}

static PyObject*
MyObject_sub(MyObject *Self, PyObject *Arg)
{
   MyObject* rv = NULL;
   if ( PyInt_Check(Arg) )
   {
      long c_long = PyInt_AS_LONG(Arg);
      rv = newMyObject(Self->my_num - c_long);
   } else if ( MyObject_Check(Arg) )
   {
      rv = newMyObject(Self->my_num - ((MyObject*)Arg)->my_num);
   } else
   {
      PyErr_SetString(PyExc_TypeError, "Only a number or another
MyObject can be subtracted from a MyObject");
      return NULL;
   }
   if ( rv == NULL )
       return NULL;
   return (PyObject *)rv;
}

static PyNumberMethods MyObject_as_number = {
   (binaryfunc)MyObject_add,   
   (binaryfunc)MyObject_sub,   
   (binaryfunc)0,      
   (binaryfunc)0,               
   (binaryfunc)0,            
   (binaryfunc)0,          
   (ternaryfunc)0,          
   (unaryfunc)0,             
   (unaryfunc)0,             
   (unaryfunc)0,      
   (inquiry)0,              
   (unaryfunc)0,            
   (binaryfunc)0,             
   (binaryfunc)0,        
   (binaryfunc)0,         
   (binaryfunc)0,          
   (binaryfunc)0,          
   0,                   
   (unaryfunc)0,              
   (unaryfunc)0,             
   (unaryfunc)0,            
   (unaryfunc)0,        
   (unaryfunc)0,          
   0,                        
   0,                          
   0,                 
   0,          
   0,           
   0,                
   0,                     
   0,               
   0,                
   0,              
   0,               
};

static PyTypeObject MyObject_Type = {
   PyObject_HEAD_INIT(NULL)
   0,
   "MyObject",
   sizeof(MyObject),
   0,
   (destructor)   MyObject_dealloc,
   (printfunc)    MyObject_print,
   (getattrfunc)  MyObject_getattr,
   (setattrfunc)  MyObject_setattr,
   (cmpfunc)      MyObject_compare,
   (reprfunc)     0,
   &MyObject_as_number,
   0,
   0,
   (hashfunc)     0,
   (ternaryfunc)  0,
   (reprfunc)     0,
};

***END CODE SNIPPET***

And in my python session i get the following error:

C:\test>python
ActivePython 2.1.1, build 212 (ActiveState)
Python 2.1.1 (#20, Jul 26 2001, 11:38:51) [MSC 32 bit (Intel)] on
win32
Type "copyright", "credits" or "license" for more information.
>>> from MyObject_Module import *
>>> foo = MyObject(9)
>>> print foo
9
>>> foo + 8
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: unsupported operand types for +
>>>

im posting the full module (MyObject_Module.c) below.  Any help is
appreciated greatly.

Thanks very much,

Doug
doug_bartholomew99 at yahoo.com


***********MyObject_Module.c***********

#include "Python.h"

static PyObject *ErrorObject;

typedef struct {
   PyObject_HEAD
   long my_num;
   PyObject *x_attr;          
} MyObject;

staticforward PyTypeObject MyObject_Type;

#define MyObject_Check(v) ((v)->ob_type == &MyObject_Type)

static MyObject *
newMyObject(const long arg_int)
{
   MyObject *Self;
   Self = PyObject_New(MyObject, &MyObject_Type);
   if (Self == NULL)
      return NULL;
   Self->my_num = arg_int;
   Self->x_attr = NULL;
   return Self;
}

static void
MyObject_dealloc(MyObject *Self)
{
   Py_XDECREF(Self->x_attr);
   PyObject_Del(Self);
}

static int
MyObject_print(MyObject *Self, FILE *fp, int flags)
     /* flags -- not used but required by interface */
{
   flags;
   fprintf(fp, "%d", Self->my_num);
   return 0;
}

static PyObject *
MyObject_demo(MyObject *Self, PyObject *Args)
{
   if (!PyArg_ParseTuple(Args, ":demo"))
      return NULL;
   Py_INCREF(Py_None);
   return Py_None;
}

static PyMethodDef MyObject_methods[] = {
   {"demo",  (PyCFunction)MyObject_demo,   METH_VARARGS},
   {NULL,   NULL} 
};

static PyObject *
MyObject_getattr(MyObject *self, char *name)
{
   if (self->x_attr != NULL) {
      PyObject *v = PyDict_GetItemString(self->x_attr, name);
      if (v != NULL) {
         Py_INCREF(v);
         return v;
      }
   }
   return Py_FindMethod(MyObject_methods, (PyObject *)self, name);
}

static int
MyObject_setattr(MyObject *self, char *name, PyObject *v)
{
   if (self->x_attr == NULL) {
      self->x_attr = PyDict_New();
      if (self->x_attr == NULL)
         return -1;
   }
   if (v == NULL) {
      int rv = PyDict_DelItemString(self->x_attr, name);
      if (rv < 0)
         PyErr_SetString(PyExc_AttributeError,
                 "delete non-existing attribute");
      return rv;
   }
   else
      return PyDict_SetItemString(self->x_attr, name, v);
}

static int
MyObject_compare(MyObject *Right, MyObject *Left)
{
   return ( Right->my_num < Left->my_num ) ? -1 :
          (( Right->my_num > Left->my_num ) ? +1 : 0);
}

static PyObject*
MyObject_add(MyObject *Self, PyObject *Arg)
{
   long c_long; 
   MyObject* rv;
   if ( !PyInt_Check(Arg) )
   {
      PyErr_SetString(PyExc_TypeError, "Should add a number to
MyObject");
      return NULL;
   }
   c_long = PyInt_AS_LONG(Arg);
   rv = newMyObject(Self->my_num + c_long);
   if ( rv == NULL )
       return NULL;
   return (PyObject *)rv;
}

static PyObject*
MyObject_sub(MyObject *Self, PyObject *Arg)
{
   MyObject* rv = NULL;
   if ( PyInt_Check(Arg) )
   {
      long c_long = PyInt_AS_LONG(Arg);
      rv = newMyObject(Self->my_num - c_long);
   } else if ( MyObject_Check(Arg) )
   {
      rv = newMyObject(Self->my_num - ((MyObject*)Arg)->my_num);
   } else
   {
      PyErr_SetString(PyExc_TypeError, "Only a number or another
MyObject can be subtracted from a MyObject");
      return NULL;
   }
   if ( rv == NULL )
       return NULL;
   return (PyObject *)rv;
}

static PyNumberMethods MyObject_as_number = {
   (binaryfunc)MyObject_add,   
   (binaryfunc)MyObject_sub,   
   (binaryfunc)0,      
   (binaryfunc)0,               
   (binaryfunc)0,            
   (binaryfunc)0,          
   (ternaryfunc)0,          
   (unaryfunc)0,             
   (unaryfunc)0,             
   (unaryfunc)0,      
   (inquiry)0,              
   (unaryfunc)0,            
   (binaryfunc)0,             
   (binaryfunc)0,        
   (binaryfunc)0,         
   (binaryfunc)0,          
   (binaryfunc)0,          
   0,                   
   (unaryfunc)0,              
   (unaryfunc)0,             
   (unaryfunc)0,            
   (unaryfunc)0,        
   (unaryfunc)0,          
   0,                        
   0,                          
   0,                 
   0,          
   0,           
   0,                
   0,                     
   0,               
   0,                
   0,              
   0,               
};

static PyTypeObject MyObject_Type = {
   PyObject_HEAD_INIT(NULL)
   0,
   "MyObject",
   sizeof(MyObject),
   0,
   (destructor)   MyObject_dealloc,
   (printfunc)    MyObject_print,
   (getattrfunc)  MyObject_getattr,
   (setattrfunc)  MyObject_setattr,
   (cmpfunc)      MyObject_compare,
   (reprfunc)     0,
   &MyObject_as_number,
   0,
   0,
   (hashfunc)     0,
   (ternaryfunc)  0,
   (reprfunc)     0,
};

static PyObject *
MyObject_Module_new(PyObject *Self, PyObject *Args)
{
   MyObject *rv;

   long arg_long;
   if ( PyArg_ParseTuple(Args, "l:MyObject", &arg_long) )
      rv = newMyObject(arg_long);
   else if ( PyArg_ParseTuple(Args, ":MyObject") )
   {
      PyErr_Clear();
      rv = newMyObject(0);
   }
   else
      return NULL;

   if ( rv == NULL )
       return NULL;
   return (PyObject *)rv;
}

static PyMethodDef MyObject_Module_methods[] = {
   {"MyObject",    MyObject_Module_new,     METH_VARARGS},
   {NULL,          NULL}      /* sentinel */
};

#ifdef __cplusplus
extern "C"
#endif
 __declspec(dllexport)
void initMyObject_Module(void)
{
   PyObject *m, *d;
   MyObject_Type.ob_type = &PyType_Type;
   m = Py_InitModule("MyObject_Module", MyObject_Module_methods);
   d = PyModule_GetDict(m);
   ErrorObject = PyErr_NewException("MyObject_Module.error", NULL,
NULL);
   PyDict_SetItemString(d, "error", ErrorObject);
}



More information about the Python-list mailing list