pythonccpython

How to use a shared object of a python script in a C code?


I would like to prepare a shared object (.so) from a python module. I came across Cython which would :

But, I am interested in reading this shared object from a C code. When I wrote a sample C code to read a .so, it throws a error saying that the methods that are actually present in .pyx are not present in the .so object.

I would like to know :

Thanks,

Python code (saved as square_number.pyx)

def square_me(int x):
    return x * x

Corresponding setup.py file for Cython

from distutils.core import setup
from Cython.Build import cythonize

setup(
    ext_modules=cythonize("square_number.pyx"),
     )

Command line statements for converting the above .pyx to a .So (through cython)

python setup.py build_ext --inplace

This would create a square_number.so in the same folder. Now, I renamed this to libSquareNumber.so

C code for reading the .so

#include<stdio.h>

int main(int argc,char *argv[])
{
    int result;

    result=square_me(2);

    printf("Sum of entered numbers = %d\n",result);

    return 0;
 }

When I am trying to compile and build an executable from the above command, I am getting an error

Compilation of C code:

gcc -L/home/USRNAME/work/cython-codes/squaring/ -Wall -o test so_reader_in_c.c -lSquareNumber

Error

so_reader_in_c.c: In function ‘main’:
so_reader_in_c.c:11:4: warning: implicit declaration of function ‘square_me’ [-    Wimplicit-function-declaration]
result=square_me(2);
^
/tmp/ccE5vIOH.o: In function `main':
so_reader_in_c.c:(.text+0x1a): undefined reference to `square_me'
collect2: error: ld returned 1 exit status

Solution

  • change square_number.pyx to:

    cdef public int square_me(int x):
        return x * x
    

    After running the "setup.py" it will generate the header file "square_number.h". Include that in your main application. See below:

    change your "main" function to something like:

    #include <Python.h>
    #include "square_number.h"
    
    int main()
    {
        Py_Initialize();
        initsquare_number();
        printf("%d",square_me( 4 ) );
        Py_Finalize();
        return 0;
    }
    

    While compiling this make sure you link against libpython.so and libsquare_number.so You will also need to take care of include directory search path for "Python.h" by giving -I flag to gcc.

    For more information see: http://docs.cython.org/src/userguide/external_C_code.html