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

Michele De Stefano micdestefano at gmail.com
Wed Dec 23 12:19:50 CET 2009


I'm not sure if this can help.
http://code.google.com/p/mds-utils
If you try to use Boost Python and the
mds_utils::python::support_random_access< Derived >
class, contained into container_operators.hpp of the mds-utils library
(http://code.google.com/p/mds-utils), may be you can easily define a
subscriptable container (look at the example program attached to the
library documentation).

Another approach I think is to use the Boost Python's indexing suite
(http://www.boost.org/doc/libs/1_41_0/libs/python/doc/v2/indexing.html).

Best regards.
Michele

2009/12/23 Anita A <anitaa1981 at 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 at python.org
> http://mail.python.org/mailman/listinfo/cplusplus-sig
>



-- 
Michele De Stefano
http://www.linkedin.com/in/micdestefano
http://code.google.com/p/mds-utils
http://xoomer.virgilio.it/michele_de_stefano


More information about the Cplusplus-sig mailing list