Search code examples
pythonccpython

Error when compiling CPython: Cannot Convert from PyLongObject to PyObject


I've been trying to learn to use CPython and for it, I tried creating a simple factorial function. Here is the function:

/*
long factorial(long number){
    long output = 1;

    for (long i = 1; i < number; i++){
        output *= i;}}
*/

PyLongObject factorial(PyLongObject number){

    PyLongObject output = PyLong_FromLong(1);

    for (PyLongObject i = PyLong_FromLong(1); PyObject_RichCompare(i, number, Py_LT); PyNumber_InPlaceAdd(1, i)){
        PyNumber_InPlaceMultiply(i, output);}
    return output;
}

However when I compile the program using the setup.py file, I get get the following error:

error C2440: 'function': cannot convert from 'PyLongObject' to 'PyObject *'
warning C4024: 'PyObject_RichCompare': different types for formal and actual parameter 1
warning C4024: 'PyObject_RichCompare': different types for formal and actual parameter 2
warning C4024: 'PyNumber_InPlaceAdd': different types for formal and actual parameter 1
warning C4024: 'PyNumber_InPlaceAdd': different types for formal and actual parameter 2
error C2440: 'function': cannot convert from 'PyLongObject' to 'PyObject *'
warning C4024: 'PyNumber_Multiply': different types for formal and actual parameter 1
warning C4024: 'PyNumber_Multiply': different types for formal and actual parameter 2
error C2440: '=': cannot convert from 'PyObject *' to 'PyLongObject'
error C2440: 'initializing': cannot convert from 'PyObject *' to 'PyLongObject'
error C2440: 'initializing': cannot convert from 'PyObject *' to 'PyLongObject'
error C2440: 'initializing': cannot convert from 'PyObject *' to 'PyLongObject'
error: command 'C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools\\VC\\Tools\\MSVC\\14.27.29110\\bin\\HostX86\\x64\\cl.exe' failed with exit status 2

I'm guessing this is because I'm improperly using the PyLongObject and PyObject*. I tried looking at the CPython docs to try finding the issue but couldn't see what I'm doing wrong. How can I fix my code to work?

Note: I'm using Python Objects because they provide me an arbitrary length precision.

Alright, so I fixed the code to compile properly, but I have no idea why. This is what I changed it to:

PyObject* factorial(PyObject* number){

    PyObject* output = PyLong_FromLong(1);

    for (PyObject* i = PyLong_FromLong(1); PyObject_RichCompare(i, number, Py_LT); PyNumber_InPlaceAdd(1, i)){
        PyNumber_InPlaceMultiply(i, output);}
    return output;
}

Why does this code work now?


Solution

  • C-Api reference

    Check the documentation.

    PyObject* PyObject_RichCompare(PyObject *o1, PyObject *o2, int opid)
    

    First and second arguments are of type PyObject*, earlier you were passing PyLongObject. i.e. i and number

    Compiler was telling you exactly that. Same explanation goes for other function calls as well. When you changed the code, all the function calls are now receiving parameters with expected type.