Search code examples
ccpython

Error when Compiling CPython: C2440 'function': cannot convert from 'PyObject' to PyObject *'


I'm new to using CPython (and C as well) and I was trying to create an extension module to calculate nCk. However, I'm coming across this really annoying error when compiling. Here's my code:

PyObject* combination(PyObject* n, PyObject* k){
    PyObject* output = ONE;
    return PyNumber_TrueDivide(factorial(n), PyNumber_Multiply(factorial(k), factorial(PyNumber_Subtract(n, k))));
}
static PyObject* BezierCurve_combination(PyObject* self, PyObject* args){
    PyObject n, k;

    if (!PyArg_ParseTuple(args, "OO", &n, &k))
        return NULL;
    
    /* This return statement is line 60*/
    return Py_BuildValue("O", combination(n, k));
}

And here is the error message:

(60): error C2440: 'function': cannot convert from 'PyObject' to 'PyObject *'
(60): warning C4024: 'combination': different types for formal and actual parameter 1
(60): warning C4024: 'combination': different types for formal and actual parameter 2

What is causing this error? A similar program works really well for a factorial function definition (it contains just 1 PyObject* argument.) How can I fix this?


Solution

  • You can never have a PyObject in your program like that. They're always pointers to PyObjects.

    Use PyObject *n, *k; - or, if in doubt,

    PyObject *n;
    PyObject *k;
    

    Furthermore, you must always check the return value of each and every function in a Python exception, excepting if you're just returning it from your function. Thus you may not write

    return PyNumber_TrueDivide(factorial(n),
           PyNumber_Multiply(factorial(k), factorial(PyNumber_Subtract(n, k))));
    

    You can only write

    return PyNumber_TrueDivide(dividend, divisor);
    

    For the inner calls you must check that they're not NULL separately, and if they are it signifies an exception that you must handle, or throw out (by returning NULL from your function).