[C++-sig] Trying to implement subscriptable type in c++.

Anita A anitaa1981 at gmail.com
Wed Dec 23 04:20:31 CET 2009

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

extern const char* code;

int main(int argc, char *argv[])

    PyObject* myModule = Py_InitModule3("test", module_methods, "test module");

    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;
        return 1;

    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__']
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__']

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.

More information about the Cplusplus-sig mailing list