Взаимодействие с кодом Python

Подключение Python

Последнее обновление: 02.05.2023

Язык программирования Python обладает большими возможностями, имеет богатый функционал и библиотеки, написание которых на языке Си может занять продолжительное время, особенно это касается сферы машинного обучения. И было бы неплохо просто взять готовую функциональность на Python и инкорпорировать в программу на C. И Python позволяет это сделать, предоставляя такую функциональность, как Embedded Python (встраиваемый Python). То есть мы можем встроить в программу на C интерпретатор Python и выполнять в программе на C код на языке Python. Рассмотрим, как это сделать.

Настройка и компиляция на Windows

Для работы на ОС Windows прежде всего нам нужно узнать путь к установленному интерпретатору Python. Например, в моем случае это путь C:\Users\eugen\AppData\Local\Programs\Python\Python311. Для упрощения работу установим в переменных среды переменную PYTHONHOME. Она должна указывать на путь к каталогу, где установлен Python. Эта переменная будет использоваться для поиска нужных библиотек:

Настройка PYTHONHOME для Embedded 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

Python.h в программе на языке C

В программе сначала вызываем функцию 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

Компиляция на Linux несколько отличается. Для компиляции на Ubuntu применяется следующая команда:

gcc -Wall $(python3-config --cflags) -o app app.c $(python3-config --embed --ldflags)

Использование библиотек Python

Подобным образом можно использовать более сложный код 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 в программе на языке C

Выполнение файла с кодом Python

Если инструкций на 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
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850