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

Reply via email to