In Python C API you cannot define a __getitem__ method; instead define a tp_as_mapping slot. See:
http://docs.python.org/c-api/typeobj.html#tp_as_mapping 2009/12/23 Anita A <anitaa1...@gmail.com> > Hi all, > > I am trying to implement a subscriptable type in c++ (equivalent to python > dict), but I get a 'type is unsubscriptable' error. Here is a minimal > code sample I tried: > > -------------------------------------------------------------------------- > #include <Python.h> > #include <iostream> > #include "pyerror.hpp" > > ///////////////////////////////////////////////////////// > PyObject* getitem(PyObject* self, PyObject* args) > { > std::cout << "getitem" << std::endl; > return PyString_FromString("this is an item"); > } > > PyMethodDef method[] = { > {"__getitem__", &getitem, METH_VARARGS, ""}, > {0, 0, 0, 0} > }; > > static PyMethodDef module_methods[] = { > { 0, 0, 0, 0 } > }; > > struct MyObject > { > PyObject_HEAD > }; > > extern const char* code; > > int main(int argc, char *argv[]) > { > Py_InitializeEx(0); > > PyObject* myModule = Py_InitModule3("test", module_methods, "test > module"); > assert(myModule); > > PyTypeObject myType; > memset(&myType, 0, sizeof(PyTypeObject)); > > myType.tp_name = "myType"; > myType.tp_basicsize = sizeof(MyObject); > myType.tp_methods = method; > if (PyType_Ready(&myType) < 0) > { > std::cout << "type error" << std::endl; > return 1; > } > > PyModule_AddObject(myModule, myType.tp_name, (PyObject*)&myType); > > PyObject* m = PyImport_AddModule("__main__"); > PyObject* d = PyModule_GetDict(m); > MyObject* odef = PyObject_New(MyObject, &myType); > PyDict_SetItemString(d, "obj", (PyObject*)odef); > > PyObject* rv = PyRun_String(code, Py_file_input, d, d); > if(rv == 0) > { > std::cout << "run error" << std::endl; > printException(); > return 1; > } > > Py_Finalize(); > std::cout << "Done.\n"; > > return 0; > } > > const char* code = > "print dir(obj)\n" > "x = obj.__getitem__(1)\n" > "print 'direct call:', x\n" > "x = obj[1]\n" > ; > > -------------------------------------------------------------------------- > Compile and run session. > -------------------------------------------------------------------------- > $ g++ -I/usr/include/python2.6 pymin.cpp -lpython2.6 > $ ./a.out > ['__class__', '__delattr__', '__doc__', '__format__', > '__getattribute__', '__getitem__', '__hash__', '__init__', '__new__', > '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', > '__sizeof__', '__str__', '__subclasshook__'] > getitem > direct call: this is an item > run error > Error in execution: > Traceback (most recent call last): > line 4, in ?? > <type 'exceptions.TypeError'>: 'myType' object is unsubscriptable > -------------------------------------------------------------------------- > > As you can see, when I call __getitem__() directly, it works, but when I > call it as a subscriptable object, I get an error. What am I missing? > > A simple python equivalent class works as expected: > -------------------------------------------------------------------------- > class Testi: > def __getitem__(self, idx): > return 10 > > if __name__ == '__main__': > x = Testi() > print dir(x) > print x['a'] > -------------------------------------------------------------------------- > Run session. > -------------------------------------------------------------------------- > $ python tst.py > ['__doc__', '__getitem__', '__module__'] > 10 > -------------------------------------------------------------------------- > > I had tried using the PyMappingMethods structure as documented, but there > is apparently no way to implement the __contains__() method, that is, to > check if a key is present in the dict. > > Any help would be appreciated. > _______________________________________________ > Cplusplus-sig mailing list > Cplusplus-sig@python.org > http://mail.python.org/mailman/listinfo/cplusplus-sig > -- Gustavo J. A. M. Carneiro INESC Porto, Telecommunications and Multimedia Unit "The universe is always one step beyond logic." -- Frank Herbert
_______________________________________________ Cplusplus-sig mailing list Cplusplus-sig@python.org http://mail.python.org/mailman/listinfo/cplusplus-sig