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