To update my previous email, I found the problem, but I have a new problem.  

Previously I cast PyObject * value_ptr = (PyObject * )value_1 but that's not 
correct.  Instead I used PyObject * value_ptr = PyLong_FromLong(value_1) and 
that works.  HOWEVER, while PyObject_CallFunctionObjArgs does work now, it 
returns -1, which is not the right answer for random.seed.  I use "long 
return_val = PyLong_AsLong(p_seed_calc);" to convert it to a long.  

So my question is why do I get -1 as return value?  When I query p_seed calc : 
get:

(gdb) p p_seed_calc
$2 = (PyObject *) 0x7ffff69be120 <_Py_NoneStruct>

Thanks again.

Jen




Sep 29, 2022, 13:02 by python-list@python.org:

> Thanks very much to @MRAB for taking time to answer.  I changed my code to 
> conform to your answer (as best I understand your comments on references), 
> but I still get the same error.  My comments continue below the new code 
> immediately below.  
>
> int64_t Get_LibModules(int64_t * return_array)
> {
> PyObject * pName_random = PyUnicode_FromString("random");
> PyObject * pMod_random = PyImport_Import(pName_random);
>
> Py_INCREF(pName_random);
> Py_INCREF(pMod_random);
>
> if (pMod_random == 0x0){
> PyErr_Print();
> return 1;}
>
> PyObject * pAttr_seed = PyObject_GetAttrString(pMod_random, "seed");
> PyObject * pAttr_randrange = PyObject_GetAttrString(pMod_random, "randrange");
>
> Py_INCREF(pAttr_seed);
> Py_INCREF(pAttr_randrange);
>
> return_array[0] = (int64_t)pAttr_seed;
> return_array[1] = (int64_t)pAttr_randrange;
>
> return 0;
> }
>
> int64_t C_API_2(PyObject * pAttr_seed, Py_ssize_t value_1)
> {
> PyObject * value_ptr = (PyObject * )value_1;
> PyObject * p_seed_calc = PyObject_CallFunctionObjArgs(pAttr_seed, value_ptr, 
> NULL);
>
> if (p_seed_calc == 0x0){
>     PyErr_Print();
>     return 1;}
>
> //Prepare return values
> long return_val = PyLong_AsLong(p_seed_calc);
>
> return return_val;
> }
>
> So I incremented the reference to all objects in Get_LibModules, but I still 
> get the same segfault at PyObject_CallFunctionObjArgs.  Unfortunately, 
> reference counting is not well documented so I’m not clear what’s wrong. 
>
>
>
>
> Sep 29, 2022, 10:06 by pyt...@mrabarnett.plus.com:
>
>> On 2022-09-29 16:54, Jen Kris via Python-list wrote:
>>
>>> Recently I completed a project where I used PyObject_CallFunctionObjArgs 
>>> extensively with the NLTK library from a program written in NASM, with no 
>>> problems.  Now I am on a new project where I call the Python random 
>>> library.  I use the same setup as before, but I am getting a segfault with 
>>> random.seed.
>>>
>>> At the start of the NASM program I call a C API program that gets PyObject 
>>> pointers to “seed” and “randrange” in the same way as I did before:
>>>
>>> int64_t Get_LibModules(int64_t * return_array)
>>> {
>>> PyObject * pName_random = PyUnicode_FromString("random");
>>> PyObject * pMod_random = PyImport_Import(pName_random);
>>>
>> Both PyUnicode_FromString and PyImport_Import return new references or null 
>> pointers.
>>
>>> if (pMod_random == 0x0){
>>> PyErr_Print();
>>>
>>
>> You're leaking a reference here (pName_random).
>>
>>> return 1;}
>>>
>>> PyObject * pAttr_seed = PyObject_GetAttrString(pMod_random, "seed");
>>> PyObject * pAttr_randrange = PyObject_GetAttrString(pMod_random, 
>>> "randrange");
>>>
>>> return_array[0] = (int64_t)pAttr_seed;
>>> return_array[1] = (int64_t)pAttr_randrange;
>>>
>>
>> You're leaking 2 references here (pName_random and pMod_random).
>>
>>> return 0;
>>> }
>>>
>>> Later in the same program I call a C API program to call random.seed:
>>>
>>> int64_t C_API_2(PyObject * pAttr_seed, Py_ssize_t value_1)
>>> {
>>> PyObject * p_seed_calc = PyObject_CallFunctionObjArgs(pAttr_seed, value_1);
>>>
>>
>> It's expecting all of the arguments to be PyObject*, but value_1 is 
>> Py_ssize_t instead of PyObject* (a pointer to a _Python_ int).
>>
>> The argument list must end with a null pointer.
>>
>> It returns a new reference or a null pointer.
>>
>>>
>>> if (p_seed_calc == 0x0){
>>>      PyErr_Print();
>>>      return 1;}
>>>
>>> //Prepare return values
>>> long return_val = PyLong_AsLong(p_seed_calc);
>>>
>> You're leaking a reference here (p_seed_calc).
>>
>>> return return_val;
>>> }
>>>
>>> The first program correctly imports “random” and gets pointers to “seed” 
>>> and “randrange.”  I verified that the same pointer is correctly passed into 
>>> C_API_2, and the seed value (1234) is passed as  Py_ssize_t value_1.  But I 
>>> get this segfault:
>>>
>>> Program received signal SIGSEGV, Segmentation fault.
>>> 0x00007ffff64858d5 in _Py_INCREF (op=0x4d2) at ../Include/object.h:459
>>> 459     ../Include/object.h: No such file or directory.
>>>
>>> So I tried Py_INCREF in the first program:
>>>
>>> Py_INCREF(pMod_random);
>>> Py_INCREF(pAttr_seed);
>>>
>>> Then I moved Py_INCREF(pAttr_seed) to the second program.  Same segfault.
>>>
>>> Finally, I initialized “random” and “seed” in the second program, where 
>>> they are used.  Same segfault.
>>>
>>> The segfault refers to Py_INCREF, so this seems to do with reference 
>>> counting, but Py_INCREF didn’t solve it.
>>>
>>> I’m using Python 3.8 on Ubuntu.
>>>
>>> Thanks for any ideas on how to solve this.
>>>
>>> Jen
>>>
>>
>> -- 
>> https://mail.python.org/mailman/listinfo/python-list
>>
>
> -- 
> https://mail.python.org/mailman/listinfo/python-list
>

-- 
https://mail.python.org/mailman/listinfo/python-list

Reply via email to