[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
{
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.
More information about the Cplusplus-sig
mailing list