C API PyObject_Call segfaults with string

MRAB python at mrabarnett.plus.com
Thu Feb 10 15:43:10 EST 2022


On 2022-02-10 20:00, Jen Kris via Python-list wrote:
> With the help of PyErr_Print() I have it solved.  Here is the final code (the part relevant to sents):
> 
>     Py_ssize_t listIndex = 0;
>     pListItem = PyList_GetItem(pFileIds, listIndex);
>     pListStrE = PyUnicode_AsEncodedString(pListItem, "UTF-8", "strict");
>     pListStr = PyBytes_AS_STRING(pListStrE); // Borrowed pointer
> 
>     // Then:  sentences = gutenberg.sents(fileid) - this is a sequence item
>     PyObject *c_args = Py_BuildValue("s", pListStr);
>     PyObject *args_tuple = PyTuple_New(1);
>     PyTuple_SetItem(args_tuple, 0, c_args);
> 
>     pSents = PyObject_CallObject(pSentMod, args_tuple);
> 
>     if ( pSents == 0x0){
>         PyErr_Print();
>         return return_value; }
> 
> As you mentioned yesterday, CallObject needs a tuple, so that was the problem.  Now it works.
> 
> You also asked why I don't just use pListStrE.  I tried that and got a long error message from PyErr_Print.  I'm not far enough along in my C_API work to understand why, but it doesn't work.
> 
> Thanks very much for your help on this.
> 
You're encoding a Unicode string to a UTF-8 bytestring:

     pListStrE = PyUnicode_AsEncodedString(pListItem, "UTF-8", "strict");

then pointing to the bytes of that UTF-8 bytestring:

     pListStr = PyBytes_AS_STRING(pListStrE); // Borrowed pointer

then making a Unicode string from those UTF-8 bytes:

     PyObject *c_args = Py_BuildValue("s", pListStr);

You might was well just use the original Unicode string!

Try this instead:

    Py_ssize_t listIndex = 0;
    pListItem = PyList_GetItem(pFileIds, listIndex);
    //> pListItem?

    pSents = PyObject_CallFunctionObjArgs(pSentMod, pListItem, 0);
    //> pSents+?

    if (pSents == 0x0){
        PyErr_Print();
        return return_value;
    }

> 
> 
> Feb 9, 2022, 17:40 by songofacandy at gmail.com:
> 
>> On Thu, Feb 10, 2022 at 10:37 AM Jen Kris <jenkris at tutanota.com> wrote:
>>
>>>
>>> I'm using Python 3.8 so I tried your second choice:
>>>
>>> pSents = PyObject_CallFunctionObjArgs(pSentMod, pListItem);
>>>
>>> but pSents is 0x0.  pSentMod and pListItem are valid pointers.
>>>
>>
>> It means exception happened.
>> If you are writing Python/C function, return NULL (e.g. `if (pSents ==
>> NULL) return NULL`)
>> Then Python show the exception and traceback for you.
>>


More information about the Python-list mailing list