Compiler can't find Py_InitModule() .. is it deprecated and if so what should I use?
Asked Answered
R

2

29

I am attempting to write a C extension for python. With the code (below) I get the compiler warning:

implicit declaration of function ‘Py_InitModule’

And it fails at run time with this error:

undefined symbol: Py_InitModule

I have spent literally hours searching for a solution with no joy. I have tried multiple minor changes to syntax, I even found a post suggesting the method has been deprecated. However I find no replacement.

Here is the code:

#include <Python.h>

//a func to calc fib numbers
int cFib(int n)
{
    if (n<2) return n;
    return cFib(n-1) + cFib(n-2);
}


static PyObject* fib(PyObject* self,PyObject* args)
{
    int n;
    if (!PyArg_ParseTuple(args,"i",&n)) 
        return NULL;    
    return Py_BuildValue("i",cFib(n));
}

static PyMethodDef module_methods[] = {
    {"fib",(PyCFunction) fib, METH_VARARGS,"calculates the fibonachi number"},
    {NULL,NULL,0,NULL}
};

PyMODINIT_FUNC initcModPyDem(void)
{
    Py_InitModule("cModPyDem",module_methods,"a module");
}

If it helps here is my setup.py :

from distutils.core import setup, Extension

module = Extension('cModPyDem', sources=['cModPyDem.c'])
setup(name = 'packagename', 
    version='1.0',
    description = 'a test package',
    ext_modules = [module])

And the test code in test.py :

import cModPyDem

if __name__ == '__main__' :

    print(cModPyDem.fib(200))

Any help would be much, much appreciated.

Rhigolene answered 3/2, 2015 at 18:5 Comment(2)
what version of Python are you compiling against?Steelworks
Sorry, yes I am compiling with python3Rhigolene
R
45

The code you have would work fine in Python 2.x, but Py_InitModule is no longer used in Python 3.x. Nowadays, you create a PyModuleDef structure and then pass a reference to it to PyModule_Create.

The structure would look like:

static struct PyModuleDef cModPyDem =
{
    PyModuleDef_HEAD_INIT,
    "cModPyDem", /* name of module */
    "",          /* module documentation, may be NULL */
    -1,          /* size of per-interpreter state of the module, or -1 if the module keeps state in global variables. */
    module_methods
};

And then your PyMODINIT_FUNC function would look like:

PyMODINIT_FUNC PyInit_cModPyDem(void)
{
    return PyModule_Create(&cModPyDem);
}

Note that the name of the PyMODINIT_FUNC function must be of the form PyInit_<name> where <name> is the name of your module.

I think it would be worthwhile if you read Extending in the Python 3.x documentation. It has a detailed description of how to build extension modules in modern Python.

Retrieve answered 3/2, 2015 at 18:40 Comment(3)
Excellent - code you provided works as is except one minor change - PyMODINIT_FUNC PyInit_cModPyDem(void){} - is the correct way. Thanks, and yes it was worth going through the docs.Rhigolene
In return PyModule_Create(&ModPyDem);, the correct would be return PyModule_Create(&cModPyDem);?Litter
BTW, this gives "warning: missing initializer for field ‘m_slots’ of ‘struct PyModuleDef" in Python 3.6.8 Ubuntu 18.04.Braces
H
4

I ran into the same problem with Py_InitModule(). I started with the aforementioned Python 3 docs, specifically the "Extending and Embedding the Python Interpreter" doc. But that doc's chapter entitled "A Simple Example" leaves out details. So. I googled this scipy lecture:

http://www.scipy-lectures.org/advanced/interfacing_with_c/interfacing_with_c.html

which is in many ways more suitable for someone new to Python-C API extensions ... except it has not been updated for Python v3. So ... consult the scipy lecture, and the Python 3 docs, and this StackOverflow discussion, culling the pertinent information from each for your needs.

Holmium answered 5/5, 2016 at 3:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.