[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