Используем Python в своей программе
При разработке прикладных программ иногда возникает необходимость предоставить пользователю какую-то достаточно гибкую, но простую систему для управления программой.
Есть множество вариантов реализации таких систем, но одним из наиболее простых является встраивание в приложение интерпретатора скриптовых языков.
Реализацией этого варианта мы сегодня и займемся. В качестве скриптового языка был выбран Python из-за достаточно большого спектра применения.
Он кроссплатформенный, существуют официальные версии для Windows, Linux и MacOS. В конце концов, о мощи и потенциале этого языка может говорить хотя бы тот факт, что он используется в небезызвестной корпорации Google как основной язык программирования.
На стартКачаем с www.python.org последний релиз интерпретатора языка и устанавливаем его куда-нибудь. Проверяем наличие следующих файлов:
Python\libs\python31.lib (или libpython31.a, если вы используете gcc)
Если этих файлов нет, нужно скачать с официального сайта исходники интерпретатора и распаковать их куда-нибудь. Создайте проект в любой IDE (например, MS VS 2005) и пропишите в настройках подключаемых модулей пути к папкам с этими файлами.
Простенькая программка#include int main(int argc, char *argv[])
Теперь ее обсудим.
Первым делом подключается Python.h для получения доступа к Python API.
Перед работой с интерпретатором необходимо обязательно вызывать Py_Initialize, после ее окончания Py_Finalize. Один из способов вызвать на выполнение нужный скрипт – это функция PyRun_SimpleString. Она принимает в качестве параметра строку со скриптом и выполняет. В приведенном примере функция выведет на экран текущее время. Однако в большинстве случаев этого недостаточно.
Получение результата выполнения функцииПредположим, что нам нужна программа для построения графиков мат. функций. Если это простая функция вроде у = x + 1 ― cos(x), то проблем с вводом не возникнет, достаточно написать простой парсер выражений на основе обратной польской записи. Но функций могут быть и более сложные, например:
- Передаем параметр функции, написанной на Python-е
- Выполняем её
- Получаем результат
def func(x): if x > 3: return x + 1 elif 1 < x <= 3: return 0 else: return x ** x
Функция, вызывающая скрипт с функцией y(x) из модуля:
double compute(double x)
Обсудим использованные функции, не особо вдаваясь в подробности, т. к. цель данной статьи состоит в рассказе об основных моментах встраивания Python’а в приложения. Для получения более подробных сведений можно почитать документацию на официальном сайте.
Функции вида Py*_From* позволяют преобразовывать встроенные типы С/C++ во внутренние типы Python’а. Т. е., например, PyUnicode_FromString преобразует свой строковый параметр во внутреннее юникодовое представление Python’а для того, чтобы интерпретатор языка смог потом с ним (с параметром) работать. Функции вида Py*_As* имеют обратное действие (т.е. преобразовывают типы из внутреннего представления интерпретатора во встроенные типы C/C++).
PyImport_Import позволяет получить доступ к функциям модуля, имя которого указывается в качестве параметра. Тип параметра, разумеется, нужно предварительно преобразовать во внутреннее представление.
Py_DECREF ― макрос, высвобождающий память, занятую используемыми интерпретатором данными. Этот макрос отличается от Py_XDECREF тем, что последний может принимать нулевые значения в качестве параметра. Например, следующий фрагмент преобразует строку «mod» во внутренний тип Python’а и загружает нужный модуль.
pName = PyUnicode_FromString("mod"); pModule = PyImport_Import(pName); Py_DECREF(pName);
После этого объект, содержащий строку, более не нужен, поэтому память очищается при помощи Py_DECREF.
PyObject_GetAttrString возвращает указатель на функцию из модуля, указанного в качестве первого параметра с именем, указанным в качестве второго.
Для передачи параметров функциям используются так называемые «tuples». Далее для простоты будем называть их кортежами. Кортежи – наборы определенного количества значений разных типов. Для создания нового кортежа используется функция PyTuple_New с указанием нужного числа передаваемых аргументов. Потом кортеж заполняется значениями при помощи PyTuple_SetItem, первый аргумент которой – кортеж, второй – порядковый номер аргумента, а третий – его значение. После этого можно вызвать функцию PyObject_CallObject, передав ей функцию и кортеж аргументов. Теперь организация ввода пользователем исходных данных не составляет проблемы.