Question

I've been playing around with the Python C API for a while. I like it a lot but today I hit a roadblock. I have a Python extension that has a function which expects one or two dictionaries as argument. I fear I might have misunderstood how PyDict_Check, or PyArg_ParseTuple works. Here's a dumbed down example:

static PyObject * doStuffToOtherStuff(MyCustomPyObject *self, PyObject *args) {
  char const *fmt = "OO";
  PyObject dict1, dict2;

  if (!PyArg_ParseTuple(args, fmt, &dict1, &dict2))
    return NULL;

  int hasDict1 = PyDict_Check(&dict1);
  int hasDict2 = PyDict_Check(&dict2);

  printf("%d %d\n");

  Py_INCREF(Py_None);
  return Py_None;
}

When built and imported I call it like this for example:

myClass.doStuffToOtherStuff(dict(), None)

I expect this to print 1 0 but it actually prints 1 1 . So does: myClass.doStuffToOtherStuff(None, None) myClass.doStuffToOtherStuff(None, dict()) myClass.doStuffToOtherStuff({}, None) #etc...

If I change PyDict_Check to PyDict_CheckExact it prints 0 0 instead, no matter what I pass as arguments.

Any insight will be much appreciated.

Was it helpful?

Solution

PyArg_ParseTuple with O arguments expects a pointer to a PyObject *, not a pointer to a PyObject (i.e. the variadic argument should be of type PyObject **).

So your code should be:

  char const *fmt = "OO";
  PyObject *dict1, *dict2;

  if (!PyArg_ParseTuple(args, fmt, &dict1, &dict2))
    return NULL;

  int hasDict1 = PyDict_Check(dict1);
  int hasDict2 = PyDict_Check(dict2);

  // ...
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top