pythoncdistutilspython-c-extension

Using multiples C codes in one extension module Python


I have used C code in a Python project like in this tutorial. I built an extension so that it was possible to call the A function present in the main.c code through Python. However, function A calls other various functions that are present in a file called code.c, and I'm having trouble using those functions.

There are no problems if all the functions are placed in main.c, but I would like to modularize this project for organizational reasons!

The setup.py for building the modules is as follows.

ext       =  [
                 Extension(
                 'main',
                 sources = ['main.c'] ,
                 extra_compile_args=['-lpq'] ,
                 extra_link_args = ['-L/usr/local/pgsql/lib','-lpq'],
                 language=['c']
                 )
            ]

setup(name='project', version='1.0', ext_modules = ext)

How could I modify it so that the code.c functions could be used inside main.c without any problems?

Here is an outline of the situation:

main.c

#include <Python.h>
#include "code.h"

//....

void send(char* name)
{
   //DO SOMETHING
   function_from_code(name)
}

code.c

.....

#include "code.h"

void function_from_code(char* name)
{
   //DO SOMETHING
}  

and then the Python code:

import main

...

main.send("My Name")

So in this way, the python code calls the function of module main C (so far so good). At the moment main.c calls a function from code.c, it throws the following error:

ImportError: /usr/local/lib/python2.7/dist-packages/main.so: undefined symbol: function_from_code

Apparently, using #include is not enough.


Solution

  • This is too long for a comment and I'm not sure that it will fix the problem. I think it's just because it doesn't compile code.c and code.h when they are not listed explicitly as source (see "Extension names and packages").

    Personally I would use either the depends argument for the Extension:

    from glob import glob
    
    ext =  [Extension('main',
                      sources=['main.c'] ,
                      depends=glob('*.c') + glob('*.h'),
                      extra_compile_args=['-lpq'] ,
                      extra_link_args=['-L/usr/local/pgsql/lib','-lpq'],
                      language=['c']
                      )
            ]
    

    or list all the files in source:

    ext =  [Extension('main',
                      sources=['main.c', 'code.h', 'code.c'] ,
                      extra_compile_args=['-lpq'] ,
                      extra_link_args=['-L/usr/local/pgsql/lib','-lpq'],
                      language=['c']
                      )
            ]
    

    Not sure if the order of the source files or depends files matters...