On 2022-09-29 21:47, Jen Kris wrote:
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.
random.seed returns None, so when you call PyObject_CallFunctionObjArgs
it returns a new reference to Py_None.
If you then pass to PyLong_AsLong a reference to something that's not a
PyLong, it'll set an error and return -1.
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>
Exactly. It's Py_None, not a PyLong.
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