PyObject_CallObject failing on bytearray method
<p>In the following code I create a pointer to a PyObject, representing a bytearray,  using the Python C API. I then extract the method "endswith" from the bytearray and try to call it on the original bytearray itself, expecting it to return <code>Py_True.</code> However, it returns <code>NULL</code> and the program prints "very sad".</p>

<pre><code>#include&lt;Python.h&gt;
#include&lt;iostream&gt;
int main()
{
    Py_Initialize();
    //make a one-byte byte array
    PyObject* oneByteArray = PyByteArray_FromStringAndSize("a", 1);
    //get the method "endswith" from the object at oneByteArray
    PyObject* arrayEndsWith = PyObject_GetAttrString(oneByteArray, "endswith");
    //ask python if "a" ends with "a"
    PyObject* shouldbetrue = PyObject_CallObject(arrayEndsWith, oneByteArray);

    if (shouldbetrue == Py_True) std::cout &lt;&lt; "happy\n";
    if(shouldbetrue == NULL)std::cout &lt;&lt; "very sad\n";

    Py_Finalize();
    return 0;
}
</code></pre>

<p>I have checked in Python that for bytearrays, <code>foo</code> and <code>bar</code>, <code>foo.endswith(bar)</code> returns a Boolean. I also added <code>PyCallable_Check(arrayEndsWith)</code> to the code above and verified that the object is callable. What is my mistake?</p>

<p>If you add the line <a href="https://docs.python.org/2/c-api/exceptions.html" rel="nofollow"><code>PyErr_PrintEx(1)</code></a> it helpfully tells you:</p>

<blockquote>
  <p>TypeError: argument list must be a tuple</p>
</blockquote>

<p>This is confirmed by <a href="https://docs.python.org/2/c-api/object.html" rel="nofollow">the documentation for <code>PyObject_CallObject</code></a>:</p>

<blockquote>
  <p>Call a callable Python object callable_object, with arguments given by
  the tuple args.</p>
</blockquote>

<p>There's a whole bunch of ways of calling functions from the C-api. I picked one that doesn't require a tuple and it works for me (but pick the one you like):</p>

<pre><code>PyObject* shouldbetrue = PyObject_CallFunctionObjArgs(arrayEndsWith, oneByteArray,NULL);
</code></pre>

python c++ python-c-api