Search code examples
pythoncpython-extensions

How would I create a Python library that is extended by using C?


My goal is to create a Python library that I can import into any of my projects, and I wish to have the library made faster by the use of the C language (similar to how NumPy works).

However, after following many different tutorials and videos, I always reach the same error, and am unable to complete the process that the tutorial says I should be able to. I have been following this tutorial from TutorialsPoint: https://www.tutorialspoint.com/python/python_further_extensions

I have tried googleing the errors though nothing of any value has come of it.

I am running Windows 10 64 bit on my PC, and have both the 32 and 64 bit versions of Python installed (I believed the problem may have had something to do with the incorrect Python version). I have followed the tutorial exactly and have done exactly what it says to do, however, I always result in the same outcome of an error when installing (building?) it.

Here is my C code (named hello.c), it is copied and pasted from the tutorial:

#include <Python.h>

static PyObject* helloworld(PyObject* self) {
   return Py_BuildValue("s", "Hello, Python extensions!!");
}

static char helloworld_docs[] =
   "helloworld( ): Any message you want to put here!!\n";

static PyMethodDef helloworld_funcs[] = {
   {"helloworld", (PyCFunction)helloworld,
      METH_NOARGS, helloworld_docs},
      {NULL}
};

void inithelloworld(void) {
   Py_InitModule3("helloworld", helloworld_funcs,
                  "Extension module example!");
}

Here is my python setup.py code, this is also copied and pasted from the tutorial, though I have entered the directory to my hello.c file :

from distutils.core import setup, Extension
setup(name='helloworld', version='1.0', ext_modules=[Extension('helloworld', ['C:/Users/penci/OneDrive/Python3.7_64bit/Lib/site-packages/PythonLib/CCode/hello.c'])])

Once I have done this and saved them all (in the same file) the tutorial says to run the setup.py script with "install" after it. In the tutorial, it says that it should then create the required scipts and data, and that I should be able to import the python package into my code. However, when I run this, I get one of two things, depending on how I run it.

  1. I open Command Prompt, run the setup.py with the install after it, just as it shows in the tutorial. This method of running the program will either give me an error code 1120, or it will print out the following:

    running install
    running build
    running build_ext
    running install_lib
    copying build\lib.win-amd64-3.7\helloworld.cp37-win_amd64.pyd -> C:\Users\penci\OneDrive\Python3.7_64bit\Lib\site-packages
    running install_egg_info
    Writing C:\Users\penci\OneDrive\Python3.7_64bit\Lib\site-packages\helloworld-1.0-py3.7.egg-info
    

    This is what I believe is meant to happen, however, when I try to import the script into my python code, it comes up in the code suggestion window, but says that there is "no module named helloworld" (using PyCharm Community).

  2. I open Command Prompt as an Administrator, and do the exact same thing. When I do this, it always gives me the same result:

    running install
    running build
    running build_ext
    building 'helloworld' extension
    C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.22.27905\bin\HostX86\x64\cl.exe /c /nologo /Ox /W3 /GL /DNDEBUG /MT -IC:\Users\penci\OneDrive\Python3.7_64bit\include -IC:\Users\penci\OneDrive\Python3.7_64bit\include "-IC:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.22.27905\ATLMFC\include" "-IC:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.22.27905\include" "-IC:\Program Files (x86)\Windows Kits\NETFXSDK\4.7.2\include\um" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.18362.0\ucrt" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.18362.0\shared" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.18362.0\um" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.18362.0\winrt" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.18362.0\cppwinrt" /TcC:/Users/penci/OneDrive/Python3.7_64bit/Lib/site-packages/PythonLib/CCode/hello.c /Fobuild\temp.win-amd64-3.7\Release\Users/penci/OneDrive/Python3.7_64bit/Lib/site-packages/PythonLib/CCode/hello.obj
    hello.c
    C:/Users/penci/OneDrive/Python3.7_64bit/Lib/site-packages/PythonLib/CCode/hello.c(17): warning C4013: 'Py_InitModule3' undefined; assuming extern returning int
    C:\Users\penci\OneDrive\Python3.7_64bit\Lib\site-packages\PythonLib\CCode\hello.c : fatal error C1083: Cannot open compiler generated file: 'C:\Windows\system32\build\temp.win-amd64-3.7\Release\Users\penci\OneDrive\Python3.7_64bit\Lib\site-packages\PythonLib\CCode\hello.obj': No such file or directory
    error: command 'C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Tools\\MSVC\\14.22.27905\\bin\\HostX86\\x64\\cl.exe' failed with exit status 1
    

(Sorry for the massive amount of code, I am just not sure what bit will be helpful to solve the problem)

I have tried googling the "exit status 1" though no meaningful results have appeared.


Solution

  • In your 1st point I do not have enough information to give you any help. In fact even looking at the error you get intermittently 1120 with errlook.exe displays competely unrelated messages.

    In your 2nd point the problem seems to be that the compiler isn't finding the definition of the Py_InitModule3 function. This leads to the conclusion that you are not linking the correct python library which defines that symbol.

    One easy way to achieve correct linking without having to modify the code or the setup.py script is to define an environment variable LIB that the microsoft windows linker invoked by cl.exe will look at to locate the python37.lib library.

    SET LIB=%LIB%;C:/Users/penci/OneDrive/Python3.7_64bit/libs
    

    Then you have to run the setup.py script in the same console you set the variable in. This will solve the linking problem and if no other issues arises this should allow the usage of your custom module.