Python C extension - Receiving a dict as argument
Asked Answered
B

1

5

I'm writing a C extension and I'm quite lost on how to receive a dict as an argument. As the docs don't have any specifics on how to achieve this I tried to parse the argument as a Python Object and then manipulate it as a dict:

PyTypeObject *dict;

if(!PyArg_ParseTuple(args, "o", &dict))
    return NULL;

But the code fails on the parsing:

Python 2.7.2 (default, Jun 20 2012, 16:23:33) 
[GCC 4.2.1 Compatible Apple Clang 4.0 (tags/Apple/clang-418.0.60)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import plotting
>>> plotting.plot({'wff':0})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: must be impossible<bad format char>, not dict

As far as I can understand from the error message the format char is wrong (I thought "o" should represent any Python object).

What is the best way to parse a Python dict to a C pointer? I'm digging through the documentation but I haven't found anything similar to this.

Thank you.

Biisk answered 7/11, 2012 at 18:47 Comment(2)
Shouldn't that be a capital 'O' in the PyArg_ParseTuple function?Poitiers
Post this as an answer and I'll happily accept it.Biisk
F
12

You've got a couple problems here. First of all the PyTypeObject type is specifically for the struct that defines a type. You can read more about type objects here: http://docs.python.org/2/c-api/typeobj.html It's not what you want though. For a pointer to an arbitrary Python object you want to use PyObject*.

Second, the type code for an arbitrary Python object is "O" (uppercase) not "o". If you want to do a type-check that it's a dictionary you can also use "O!" This requires you to pass the address of a type object followed by the address of the PyObject* you want to store the returned PyObject* into. For example:

PyObject* dict;
PyArg_ParseTuple(args, "O!", &PyDict_Type, &dict);

This will return the object into the *dict pointer, and raise a TypeError if it is not a dict. However unless you absolutely need it to be a dict I would recommend against this in favor of checking whether the object implements the mapping interface. But that's a different question.

Fca answered 7/11, 2012 at 19:12 Comment(2)
Do you want it to be PyArg_ParseTuple(args,"0!",&PyDict_type, &dict)Weighty
OMG! I had been searching for a lot of time for the cause a similar error. Feel like a noob after having missed seeing the capital 'O' instead of the lower case 'o'. Anyway thanks a lot!!Mitrailleuse

© 2022 - 2024 — McMap. All rights reserved.