Язык программирования Python обладает большими возможностями, имеет богатый функционал и библиотеки, написание которых на языке Си может занять продолжительное время, особенно это касается сферы машинного обучения. И было бы неплохо просто взять готовую функциональность на Python и инкорпорировать в программу на C. И Python позволяет это сделать, предоставляя такую функциональность, как Embedded Python (встраиваемый Python). То есть мы можем встроить в программу на C интерпретатор Python и выполнять в программе на C код на языке Python. Рассмотрим, как это сделать.
Для работы на ОС Windows прежде всего нам нужно узнать путь к установленному интерпретатору Python.
Например, в моем случае это путь C:\Users\eugen\AppData\Local\Programs\Python\Python311
. Для упрощения работу установим в переменных среды переменную
PYTHONHOME. Она должна указывать на путь к каталогу, где установлен Python. Эта переменная будет использоваться для поиска нужных библиотек:
Определим файл app.c со следующей программой на языке C:
#include <Python.h> int main() { Py_Initialize(); PyRun_SimpleString("print('Hello METANIT.COM')"); Py_Finalize(); return 0; }
Прежде всего, чтобы встроить Python в программу, подключаем заголовочный файл Python.h. Этот файл устанавливается вместе с другими файлами
интерпретатора Python по умолчанию. Мы его можем найти в папке интерпретатора Python в каталоге include
В программе сначала вызываем функцию Py_Initialize(). Эта функция инициализирует интерпретатор Python, таблицу модулей и устанавливает путь к модулям.
Чтобы выполнить некоторый код Python, применяется функция PyRun_SimpleString(), в которую передается код Python
PyRun_SimpleString("print('Hello METANIT.COM')");
Здесь код Python представляет вывод строки на консоль с помощью функции print()
После выполнения кода Python вызываем функцию Py_Finalize(), которая освобождает память, выделенную для интерпретатора Python.
Для компиляции в Windows используем компилятор gcc
. Выполним команду
gcc -Wall -I %PYTHONHOME%\include -L %PYTHONHOME%\libs -o app.exe app.c -lpython311 & app
При компиляции с помощью опции -I нам надо передать пусть к заголовочным файлам, а это папка %PYTHONHOME%\include
. Чтобы не писать полный путь,
заменяем его часть содержимым ранее установленной переменной PYTHONHOME
Кроме того, с помощью опции -L надо установить путь к библиотеке python. А это путь %PYTHONHOME%\libs
Поскольку в моем случае используется версия python 3.11, то указывается параметр -lpython311
В итоге при выполнении программы будет выполняться код Python, который выведет на консоль строку:
c:\C>gcc -Wall -I %PYTHONHOME%\include -L %PYTHONHOME%\libs -o app app.c -lpython311 & app Hello METANIT.COM c:\C>
При этом в программе могут быть и другие инструкции на языке C:
#include <stdio.h> #include <Python.h> int main() { printf("Python program starts\n"); Py_Initialize(); PyRun_SimpleString("print('Hello METANIT.COM')"); Py_Finalize(); printf("Python program ends\n"); return 0; }
Компиляция на Linux несколько отличается. Для компиляции на Ubuntu применяется следующая команда:
gcc -Wall $(python3-config --cflags) -o app app.c $(python3-config --embed --ldflags)
Подобным образом можно использовать более сложный код Python. В том числе с использованием сторонних библиотек Python. Например, нарисуем произвольный график
с помощью библиотек numpy
и matplotlib
. Соответственно нам надо вначале установить данные библиотеки с помощью пакетного менеджера pip:
pip install numpy pip install matplotlib
Для создания графика определим на С следующую программу:
#include <Python.h> int main() { Py_Initialize(); PyRun_SimpleString( "import numpy as np\n" "import matplotlib.pyplot as plt\n" "x = np.array(range(0, 8))\n" "y = eval('2 * x + 1')\n" "plt.title('y = 2x + 1')\n" "plt.xlabel('x')\n" "plt.ylabel('y')\n" "plt.plot(x,y)\n" "plt.show()"); Py_Finalize(); return 0; }
В данном случае сначала подключаем функционал библиотек numpy
и matplotlib
.
import numpy as np import matplotlib.pyplot as plt
Далее генерируем значения, которые отображаются по оси X:
x = np.array(range(0, 8))
Для генерации применяется функция np.array()
библиотеки Numpy, которая создает набор чисел от 0 до 7.
Далее по значениям X получаем значения Y по определенной формуле. Здесь мы рисуем график функцииy = 2x + 1
. И для вычисления значений Y применяем встроенную функцию eval()
,
которая есть в языке Python и которая вычисляет произвольное выражение.
y = eval('2 * x + 1')
Затем устанавливаем заголовок графика
plt.title('y = 2x + 1')
Устанавливаем текстовые метки для осей X и Y:
plt.xlabel('x') plt.ylabel('y')
И в конце отрисовываем график и отображаем его на экране:
plt.plot(x,y) plt.show()
Если инструкций на Python много, то их проще определить в отдельный файл. Затем в программе на языке С этот файл можно выполнить с помощью функции PyRun_SimpleFile(), которая имеет следующее определение:
int PyRun_SimpleFile(FILE *fp, const char *filename)
В качестве первого параметра передается дескриптор файла, а в качестве второго - имя файла.
Например, определим в одной папке с программой файл main.py со следующим кодом на языке Python:
print("Hello Python in C")
Здесь код просто выводит строку на консоль.
В главном файле программы на C (допустим, он называется app.c) выполним этот скрипт Python:
#include <Python.h> int main() { char filename[] = "main.py"; Py_Initialize(); FILE* fp = fopen(filename, "rb"); // открываем файл и if(fp) PyRun_SimpleFile(fp, filename); // выполняем программу python Py_Finalize(); return 0; }
Здесь сначала открываем файл в бинарном режиме для чтения и получаем указатель на файл с помощью функции fopen()
, затем выполняем файл с кодом Python. В итоге
консоль должна вывести
Hello Python in C