Search code examples
pythoncpython-c-apipyd

Unable to import Python module written in C


I have been trying to work out how to make a .pyd (Python Extension Module) file from a C script (without swig or anything else except MinGW) and have successfully built it into a .pyd.

The problem however occurs when I try and import the module.

If I run it the module runs successfully (as far as I can see) and then an error appears saying Python Has Stopped Working and it closes without executing the rest of the program.

Here is my C script (test.c):

#include <python.h>

int main()
{
    PyInit_test();
    return 0;
}

int PyInit_test()
{
    printf("hello world");
}

And Python Script (file.py):

import test
print('Run From Python Extension')

I compiled the script with:

gcc -c file.py
gcc -shared -o test.pyd test.c

I can't find any errors when compiling in command prompt and am using python 3.6 (running on Windows 10).

I can't find much on the subject and would prefer to keep away from Cython (I already know C) and Swig.

Any help to tell me what is wrong would be fantastic.


Solution

  • Creating a Python extension is completely different than writing regular C code. What you have done is simply creating a valid C program but that doesn't make sense for Python.

    That's how your program should look like (it's just a skeleton, not the proper, working code):

    #include <Python.h>
    #include <stdlib.h>
    
    static PyObject* test(PyObject* self, PyObject* args)
    {
        printf("hello world");
        return NULL;
    }
    
    static PyMethodDef test_methods[] = {
        {"test", test, METH_VARARGS, "My test method."},
        {NULL, NULL, 0, NULL} /* Sentinel */
    };
    
    PyMODINIT_FUNC init_test_methods() {
        Py_InitModule("test", test_methods);
    }
    
    int main(int argc, char** argv)
    {
        /* Pass argv[0] to the Python interpreter */
        Py_SetProgramName(argv[0]);
    
        /* Initialize the Python interpreter. Required. */
        Py_Initialize();
    
        /* Add a static module */
        init_test_methods();
    }
    

    I recommend you read more about this at the following link: http://dan.iel.fm/posts/python-c-extensions/ as well as in the official docs.