Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Call a Python function from within a C program

I have an application in C and at some point I need to solve a non-linear optimization problem. Unfortunately AFAIK there are very limited resources to do that in C (please let me know otherwise). However it is quite simple to do it in Python, e.g. scipy.optimize.minimize.

While I was trying to do that I encountered some of what it seems to be very frequent pitfalls, e.g. Python.h not found, module not loading, segmentation fault on function call, etc.

What is a quick and easy first-timer’s way to link the two programs?

like image 453
George Avatar asked Jan 30 '26 08:01

George


1 Answers

There are some things that you have to make sure are in place in order to make this work:

  1. Make sure you have Python installed (you may need the python-dev package).
  2. Locate your Python.h file, e.g. by locate Python.h. One of the occurrences should be in a sub(sub)folder in the include folder, e.g. the path should be something like ../include/python2.7/Python.h.
  3. Insert #include “<path_to_Python.h>" in your C code in order to be able to use the Python API.
  4. Use any tutorial to call your Python function. I used this one and it did the trick. However there were a couple of small points missing:

    • Whenever you use any Py<Name> function, e.g. PyImport_Import(), always check the result to make sure there was no error, e.g.

      // Load the module object
      pModule = PyImport_Import(pName);
      
      if (!pModule)
      {
          PyErr_Print();
          printf("ERROR in pModule\n");
          exit(1);
      }
      
    • Immediately after initializing the Python interpreter, i.e. after Py_Initialize();, you have to append the current path to sys.path in order to be able to load your module (assuming it is located in your current directory):

      PyObject *sys = PyImport_ImportModule("sys");
      PyObject *path = PyObject_GetAttrString(sys, "path");
      PyList_Append(path, PyString_FromString("."));
      
  5. Keep in mind that when you give the name of your Python file, it has to be without the extension .py.
  6. Lastly, you have to do the following during compiling/linking:
    • Remember the ../include/python2.7/Python.h file you used before? Include the include folder in the list of the header files directories with the -I option in the gcc options during compilation, e.g. -I /System/Library/Frameworks/Python.framework/Versions/2.7/include.
    • Also pass to the linker the folder with the required libraries. It should be inside the same folder where the include folder is located, e.g. -L /System/Library/Frameworks/Python.framework/Versions/2.7/lib, along with the -lpython2.7 option (of course adjusting it accordingly to your Python version).

Now you must be able to successfully compile and execute your C program that calls in it your Python program.

I hope this was helpful and good luck!

Sources:

  • How do you call Python code from C code?
  • http://www.linuxjournal.com/article/8497?page=0,1
  • http://www.codeproject.com/Articles/11805/Embedding-Python-in-C-C-Part-I
  • http://www.codeproject.com/Articles/11843/Embedding-Python-in-C-C-Part-II
  • Python C API doesn't load module
  • What sets up sys.path with Python, and when?
  • http://linux.die.net/man/1/gcc
  • PyObject segfault on function call
  • I have Python on my Ubuntu system, but gcc can't find Python.h
  • How do you call Python code from C code?
like image 179
George Avatar answered Feb 01 '26 21:02

George



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!