Search code examples
python-3.xpython-c-api

Python3 c api - python stops working


I was trying to get a list as an input. I've googled too. I built and installed my C-extension module in the command prompt .I am able to import the module but it did show few warnings.What it had shown me was.....

At the CMD

D:\Python\c\summa>py setup.py build
running build
running build_ext
building 'saiyanism' extension
C:\Program Files\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.13.2612
8\bin\HostX86\x86\cl.exe /c /nologo /Ox /W3 /GL /DNDEBUG /MD -IE:\python\include
 -IE:\python\include "-IC:\Program Files\Microsoft Visual Studio\2017\Community\
VC\Tools\MSVC\14.13.26128\include" "-IC:\Program Files\Windows Kits\NETFXSDK\4.6
.1\include\um" "-IC:\Program Files\Windows Kits\10\include\10.0.16299.0\ucrt" "-
IC:\Program Files\Windows Kits\10\include\10.0.16299.0\shared" "-IC:\Program Fil
es\Windows Kits\10\include\10.0.16299.0\um" "-IC:\Program Files\Windows Kits\10\
include\10.0.16299.0\winrt" "-IC:\Program Files\Windows Kits\10\include\10.0.162
99.0\cppwinrt" /TcH.c /Fobuild\temp.win32-3.6\Release\H.obj
H.c
H.c(63): warning C4133: 'function': incompatible types - from 'PyObject *' to 'c
onst char *const '
H.c(117): warning C4113: 'PyObject *(__cdecl *)(PyObject *)' differs in paramete
r lists from 'PyCFunction'
C:\Program Files\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.13.2612
8\bin\HostX86\x86\link.exe /nologo /INCREMENTAL:NO /LTCG /DLL /MANIFEST:EMBED,ID
=2 /MANIFESTUAC:NO /LIBPATH:E:\python\libs /LIBPATH:E:\python\PCbuild\win32 "/LI
BPATH:C:\Program Files\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.1
3.26128\lib\x86" "/LIBPATH:C:\Program Files\Windows Kits\NETFXSDK\4.6.1\lib\um\x
86" "/LIBPATH:C:\Program Files\Windows Kits\10\lib\10.0.16299.0\ucrt\x86" "/LIBP
ATH:C:\Program Files\Windows Kits\10\lib\10.0.16299.0\um\x86" /EXPORT:PyInit_sai
yanism build\temp.win32-3.6\Release\H.obj /OUT:build\lib.win32-3.6\saiyanism.cp3
6-win32.pyd /IMPLIB:build\temp.win32-3.6\Release\saiyanism.cp36-win32.lib
   Creating library build\temp.win32-3.6\Release\saiyanism.cp36-win32.lib and ob
ject build\temp.win32-3.6\Release\saiyanism.cp36-win32.exp
Generating code
d:\python\c\summa\h.c(112) : warning C4715: 'sumlist': not all control paths ret
urn a value
Finished generating code

D:\Python\c\summa>

Here is my c module....

H.c

#include "Python.h"
static PyObject* saiyanism(PyObject* self,PyObject* args)
    {
    const char* saiyajin;
    if(!(PyArg_ParseTuple(args,"s",&saiyajin))) return NULL;
    printf("Hello,%s.Glad to see a saiyan.\n",saiyajin);
    Py_RETURN_NONE;

    }
static PyObject* UI(PyObject* self)  //,PyObject* args)
{/*code here works properly*/
Py_RETURN_NONE;
}

static PyObject* set_all(PyObject* self,PyObject *target)//PyLong_FromLong(PyObject *item))
{
    /*some code and this too works*/
    Py_RETURN_NONE;
}

static PyObject* sumlist(PyObject* self,PyObject *args)
{
PyObject *pList;
PyObject *pItem;
Py_ssize_t n;
int i;

if (!PyArg_ParseTuple(args, "O!", &PyList_Type, &pList)) {
    PyErr_SetString(PyExc_TypeError, "parameter must be a list.");
    return NULL;
}

n = PyList_Size(pList);

for (i=0; i<n; i++) {
    pItem = PyList_GetItem(pList, i);
    if(!PyLong_Check(pItem)) {
        PyErr_SetString(PyExc_TypeError, "list items must be integers.");
        printf("%ld",PyLong_AsLong(pItem));
        Py_RETURN_NONE;
    }
}
}

static PyMethodDef sups[]=
{
    {"saiyanism",saiyanism,METH_VARARGS,""},
    {"UI",UI,METH_NOARGS,""},
    {"set_all",set_all,METH_VARARGS,""},
    {"sumlist",sumlist,METH_VARARGS,""},
    {NULL,NULL,0,NULL}
};

static struct PyModuleDef saiyanismdef={
    PyModuleDef_HEAD_INIT,
    "saiyanism",
    "sad",
    -1,
    sups
};

PyMODINIT_FUNC PyInit_saiyanism(void){
Py_Initialize();
return PyModule_Create(&saiyanismdef);
}

The problem is

when I try to import and run my sumlist function with a python list as parameter Python immediately stops .

Here is the image

I just started learning this, so if there are mistakes in my program please point them out.

Should I Pass the arguement in a different way?Where am I wrong?


Solution

  • I can see at least two mistakes in sumlist:

    1. In the code

      if(!PyLong_Check(pItem)) {
          PyErr_SetString(PyExc_TypeError, "list items must be integers.");
          printf("%ld",PyLong_AsLong(pItem));
          Py_RETURN_NONE;
      }
      

      you return None (the Python object) rather than the C NULL pointer, which is used to signal an error. You also attempt to print pItem using PyLong_AsLong - the one thing you know about pItem here is that it is not a long!

    2. (The main error that is causing you problems) What happens when you get to the end of sumlist without any errors? You do not return anything and Python is expecting you to return a PyObject*. This is what the warning is telling you:

      warning C4715: 'sumlist': not all control paths return a value

      A quick fix here would be to add Py_RETURN_NONE to the end of the function to return a None object to Python. However, you probably want to do something more useful....