[C++-sig] Trying to implement subscriptable type in c++.
Gustavo Carneiro
gjcarneiro at gmail.com
Wed Dec 23 11:45:49 CET 2009
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 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
>
--
Gustavo J. A. M. Carneiro
INESC Porto, Telecommunications and Multimedia Unit
"The universe is always one step beyond logic." -- Frank Herbert
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/cplusplus-sig/attachments/20091223/1bfabeb1/attachment-0001.htm>
More information about the Cplusplus-sig
mailing list