Trying to implement subscriptable type in c++.
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.
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 <anitaa1981@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
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@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
-- Michele De Stefano http://www.linkedin.com/in/micdestefano http://code.google.com/p/mds-utils http://xoomer.virgilio.it/michele_de_stefano
participants (3)
-
Anita A -
Gustavo Carneiro -
Michele De Stefano