4

I'm running into trouble trying to call a Python function from my C++ code.

I'm trying to call the Django function call_command, with the following parameters:

    call_command('test', stdout=content)

See here why. This runs the command without the stdout=content argument:

    PyObject_CallFunctionObjArgs(executeFunc, PyString_FromString("test"), NULL)

I can't, for the life of me, figure out how to create this keyword.

    PyDict_New();
    PyDict_SetItemString(...);

Nets me a 'stdout'='content' string, instead of stdout=content.

    Py_BuildValue("{s=s}", ... , ...) 

Does the same thing.

I can get the content PyObject no problem if necessary, I just can't seem to correctly create the stdout keyword argument without Python putting quotes (handling it as a string) at some point.

How can I call call_command('test', stdout=content) from the C API?

Robin Eisenberg
  • 1,836
  • 18
  • 26
  • See if this helps you: http://stackoverflow.com/questions/145270/calling-c-c-from-python – karthikr Jun 11 '13 at 13:49
  • Doesn't seem to be what I want. I just need to find out how to create this stdout keyword and pass it as a function call argument in C. I don't want to use external tools such as SWIG or Boost:Python. – Robin Eisenberg Jun 11 '13 at 13:57

2 Answers2

2
PyObject *args = Py_BuildValue("(s)", "test");
PyObject *kwargs = PyBuildValue("{s:O}", "stdout", content);

PyObject_Call(executeFunc, args, kwargs);

Note that even in Python, you can call the function the same way:

args = ("test",)
kwargs = {"stdout" : content}

call_command(*args,**kwargs)

"stdout" is a string with quotes here too, but it works. You are trying to get the same syntax as you use in Python, with noquotename=noquotevalue, but the syntax is just a representation. Both {"quotedname" : noquotevalue} and noquotename=noquotevalue are two different ways to represent the same thing. They both actually represent a dictionary whose key is a string and value is an object. That is what you pass as the third argument to PyObject_Call.

morningstar
  • 8,952
  • 6
  • 31
  • 42
1

Py_BuildValue("{s:O}", "stdout", content_obj)

Armin Rigo
  • 12,048
  • 37
  • 48
  • 1
    And you need `PyObject_Call()` to pass this dictionary as keywords. – Armin Rigo Jun 11 '13 at 14:18
  • `PyObject *kw = Py_BuildValue("{s:O}", "stdout", PyObject_GetAttrString(PyImport_AddModule("__main__"), "content"));` yields `{stdout:}` I need `stdout=content`. No accolades, no colon instead of =, and no quotes on stdout. Did I not understand your answer correctly? – Robin Eisenberg Jun 11 '13 at 15:11
  • In Python, a call like `foo(3, x=5)` is actually the same as `foo(*a,**k)` with `a = (3,), k = {'x': 5}`. The `PyObject_Call(f,a,k)` function can be used in C and has the same meaning as, in Python, the expression `f(*a, **k)`. There is no direct C equivalent to "a keyword stdout=content", because that syntax doesn't make sense in C. – Armin Rigo Jun 11 '13 at 21:15
  • Thank you for explaining this, I got it to work. I chose morningstar's answer for posterity, but you both solved my problem :) Thank you. – Robin Eisenberg Jun 12 '13 at 09:16