Интерпретатор Python может быть встроен в программу на C с использованием C API . Это лучше всего демонстрирует уже работающий пример:
/* File : demo.c */ /* Пример встраивания интерпретатора Python в другую программу */ #include «Python.h» main(int argc, char **argv) < /* Передает argv[0] интерпретатору Python */ Py_SetProgramName(argv[0]); /* Инициализация интерпретатора */ Py_Initialize(); /* . */ /* Выполнение операторов Python (как бы модуль __main__) */ PyRun_SimpleString(«import timen»); PyRun_SimpleString(«print time.localtime(time.time())n»); /* . */ /* Завершение работы интерпретатора */ Py_Finalize(); >
Компиляция этого примера с помощью компилятора gcc может быть выполнена, например, так:
ver=»2.3″ gcc -fpic demo.c -DHAVE_CONFIG_H -lm -lpython$ -lpthread -lutil -ldl -I/usr/local/include/python$ -L/usr/local/lib/python$/config -Wl,-E -o demo
Здесь следует отметить следующие моменты:
- программу необходимо компилировать вместе с библиотекой libpython соответствующей версии (для этого используется опция -l , за которой следует имя библиотеки) и еще с библиотеками, которые требуются для Python: libpthread , libm , libutil и т.п.)
- опция pic порождает код, не зависящий от позиции, что позволяет в дальнейшем динамически компоновать код
- обычно требуется явно указать каталог, в котором лежит заголовочный файл Python.h (в gcc это делается опцией -I )
- чтобы получившийся исполняемый файл мог корректно предоставлять имена для динамически загружаемых модулей, требуется передать компоновщику опцию -E : это можно сделать из gcc с помощью опции -Wl , -E . (В противном случае, модуль time , а это модуль расширения в виде динамически загружаемого модуля, не будет работать из-за того, что не увидит имен, определенных в libpython)
Здесь же следует сделать еще одно замечание: программа , встраивающая Python , не должна много раз выполнять Py_Initialize() и Py_Finalize() , так как это может приводить к утечке памяти. Сам же интерпретатор Python очень стабилен и в большинстве случаев не дает утечек памяти.
how2.py — Как подключить интерпретатор Python
Источник: intuit.ru
Встроить интерпретатор Python в (C ++) приложение на Windows
Этот метод грязный, но он будет работать для множества интерпретаторных сред, например. gnuplot, lua.
Мой вопрос в том, какой API я могу использовать для этой задачи. Может быть, мне нужен какой-то Win32 API?
EDIT: Мне не нужен какой-либо Python. Мне очень нужен общий метод. Так что мое приложение также может работать с gnuplot и т.д.
Yin Zhu 04 янв. 2011, в 18:27
Поделиться
Boost::Python кто-нибудь? Не то, что вы описали, но, вероятно, проще.
user395760 04 янв. 2011, в 16:42
Даже если вы используете Boost.Python, вы должны встраивать фактический интерпретатор в стиле C (хотя это не так уж и Py_Init , в основном связывая несколько Py_Init и вызывая Py_Init IIRC).
Установка интерпретатора, создание проекта в PyCharm
filmor 07 июнь 2013, в 07:48
filmor 07 июнь 2013, в 07:50
Показать ещё 1 комментарий
Поделиться:
4 ответа
Если у вас есть исходное распределение Python, вы можете посмотреть в каталоге Demo/embed для образцов. Соответствующая документация здесь.
bgporter 04 янв. 2011, в 17:03
Поделиться
Я собрал приложение «Привет мир» IActiveScript С++ ATL, которое:
- Внедряет новый класс под названием CSimpleScriptSite
- Вывод из IActiveScriptSite и IActiveScriptSiteWindow
- Вызывает CoCreateInstance в движке Python с интерфейсом IActiveSite
- Выполняет оператор Python print ‘Hello World. 5 squared is: ‘ + str(5 * 5)
- Не работает ошибка для Python . Вы должны проконсультироваться с MSDN IActiveScriptError
- Имеет функции с реализацией stub return S_OK;
- У меня есть Python 2.6, но вы можете использовать любой интерпретатор Python.
- Я использовал Python для расширений Windows, у которого есть ProgID Python , который предоставляет интерпретатор Python IActiveScript wrappers
- Однако вы можете заставить код работать с любым интерпретатором Python, который поддерживает IActiveScript , вам просто нужно обновить ProgID (например, Python.AXScript.2)
Здесь пример Python Hello World:
#include #include #define CHECKHR(stmt) < HRESULT hr = S_OK; if (FAILED(hr = (stmt))) < return hr; > > class CSimpleScriptSite : public IActiveScriptSite, public IActiveScriptSiteWindow < public: CSimpleScriptSite() : m_cRefCount(1), m_hWnd(NULL) < ZeroMemory( >// IUnknown STDMETHOD_(ULONG, AddRef)(); STDMETHOD_(ULONG, Release)(); STDMETHOD(QueryInterface)(REFIID riid, void **ppvObject); // IActiveScriptSite STDMETHOD(GetLCID)(LCID *plcid) < *plcid = 0; return S_OK; >STDMETHOD(GetItemInfo)(LPCOLESTR pstrName, DWORD dwReturnMask, IUnknown **ppiunkItem, ITypeInfo **ppti) < return TYPE_E_ELEMENTNOTFOUND; >STDMETHOD(GetDocVersionString)(BSTR *pbstrVersion) < *pbstrVersion = SysAllocString(L»1.0″); return S_OK; >STDMETHOD(OnScriptTerminate)(const VARIANT *pvarResult, const EXCEPINFO *pexcepinfo) < return S_OK; >STDMETHOD(OnStateChange)(SCRIPTSTATE ssScriptState) < return S_OK; >STDMETHOD(OnScriptError)(IActiveScriptError *pIActiveScriptError) < return S_OK; >STDMETHOD(OnEnterScript)(void) < return S_OK; >STDMETHOD(OnLeaveScript)(void) < return S_OK; >// IActiveScriptSiteWindow STDMETHOD(GetWindow)(HWND *phWnd) < *phWnd = m_hWnd; return S_OK; >STDMETHOD(EnableModeless)(BOOL fEnable) < return S_OK; >// Miscellaneous HRESULT CloseScriptEngine(); HRESULT Evaluate(LPCOLESTR szScript, VARIANT *pResult, LPCOLESTR strItemName); HRESULT Execute(LPCOLESTR szScript, LPCOLESTR strItemName); HRESULT OpenScriptEngine(CLSID HRESULT OpenScriptEngine(LPCOLESTR szScriptEngine); HRESULT SetWindow(HWND hWnd) < m_hWnd = hWnd; >private: CComPtr m_ptrIActiveScript; CLSID m_clsidScriptEngine; ULONG m_cRefCount; HWND m_hWnd; >; STDMETHODIMP_(ULONG) CSimpleScriptSite::AddRef() < return InterlockedIncrement( >STDMETHODIMP_(ULONG) CSimpleScriptSite::Release() < if (!InterlockedDecrement( delete this; return 0; >return m_cRefCount; > STDMETHODIMP CSimpleScriptSite::QueryInterface(REFIID riid, void **ppvObject) < if (riid == IID_IUnknown || riid == IID_IActiveScriptSiteWindow) < *ppvObject = (IActiveScriptSiteWindow *) this; AddRef(); return NOERROR; >if (riid == IID_IActiveScriptSite) < *ppvObject = (IActiveScriptSite *) this; AddRef(); return NOERROR; >return E_NOINTERFACE; > HRESULT CSimpleScriptSite::OpenScriptEngine(CLSID m_ptrIActiveScript = NULL; CHECKHR(CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, IID_IActiveScript, (void **) CHECKHR(m_ptrIActiveScript->SetScriptSite(this)); CComPtr ptrIActiveScriptParse; CHECKHR(m_ptrIActiveScript->QueryInterface(IID_IActiveScriptParse, (void **) CHECKHR(ptrIActiveScriptParse->InitNew()); m_clsidScriptEngine = rclsid; return S_OK; > HRESULT CSimpleScriptSite::OpenScriptEngine(LPCOLESTR szScriptEngine) < CLSID clsid; CHECKHR(CLSIDFromProgID(szScriptEngine, return OpenScriptEngine(clsid); >HRESULT CSimpleScriptSite::CloseScriptEngine() < if (!m_ptrIActiveScript) < return S_OK; >CHECKHR(m_ptrIActiveScript->SetScriptState(SCRIPTSTATE_CLOSED)); m_ptrIActiveScript = NULL; return S_OK; > HRESULT CSimpleScriptSite::Evaluate(LPCOLESTR szScript, VARIANT *pResult, LPCOLESTR strItemName) < if (!m_ptrIActiveScript) < return E_POINTER; >if (!pResult) < return E_INVALIDARG; >EXCEPINFO ei = ; CComPtr ptrIActiveScriptParse; CHECKHR(m_ptrIActiveScript->QueryInterface(IID_IActiveScriptParse, (void **) CHECKHR(ptrIActiveScriptParse->ParseScriptText(szScript, strItemName, NULL, NULL, 0, 0, SCRIPTTEXT_ISEXPRESSION, pResult, return m_ptrIActiveScript->SetScriptState(SCRIPTSTATE_CONNECTED); > HRESULT CSimpleScriptSite::Execute(LPCOLESTR szScript, LPCOLESTR strItemName) < if (!m_ptrIActiveScript) < return E_POINTER; >EXCEPINFO ei = ; CComPtr ptrIActiveScriptParse; CHECKHR(m_ptrIActiveScript->QueryInterface(IID_IActiveScriptParse, (void **) CHECKHR(ptrIActiveScriptParse->ParseScriptText(szScript, strItemName, NULL, NULL, 0, 0, 0L, NULL, return m_ptrIActiveScript->SetScriptState(SCRIPTSTATE_CONNECTED); > int _tmain(int argc, _TCHAR* argv[]) < HRESULT hr = S_OK; hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); CSimpleScriptSite *pScriptSite = new CSimpleScriptSite(); hr = pScriptSite->OpenScriptEngine(OLESTR(«Python»)); hr = pScriptSite->Execute(OLESTR(«print ‘Hello World. 5 squared is: ‘ + str(5 * 5)»), NULL); hr = pScriptSite->CloseScriptEngine(); hr = pScriptSite->Release(); ::CoUninitialize(); return 0; >
Источник: overcoder.net
Встраиваем интерпретатор Python в java-приложение с помощью проекта Panama
Пару дней назад увидел твит Брайана Гетца, но только сегодня дошли руки поиграться с примерами.

Про это и хочу кратко рассказать.
О проекте Panama на Хабре уже писали. Чтобы понять, что это и зачем, стоит прочитать интервью по ссылке. Я же просто покажу пару простых примеров того, как можно применить native binder.
Прежде всего, вам понадобится компилятор C. Если вы используете Linux или MacOS, то он у вас уже есть. Если Windows, то придётся сначала установить Build Tools for Visual Studio 2017. И, конечно же, вам потребуется OpenJDK с поддержкой «Панамы». Получить его можно либо сборкой ветки «foreign» соответствующего репозитория, либо загрузкой Early-Access билда.
Начнём с минимального примера — простой функции, складывающей два числа:
#ifndef _ADDER_H #define _ADDER_H __declspec(dllexport) int add(int, int); #endif
adder.c
#include «adder.h» __declspec(dllexport) int add(int a, int b)
Компилируем в DLL
cl /LD adder.c
И используем в java-коде
В исходнике должно быть много знакомого для тех, кто использовал JNR: объявляется интерфейс нативной библиотеки, библиотека загружается, связывается с интерфейсом и происходит вызов нативной функции. Основное отличие — использование Layout Definition Language в аннотациях для описания схемы отображения нативных данных на типы Java.
Несложно догадаться, что выражение » (i32 i32)i32 » обозначает функцию принимающую два целых 32-битных числа и возвращающую целое 32-битное число. Метка i обозначает один из трёх основных типов — целое число с порядком байт little-endian. Кроме него часто встречаются u и f — беззнаковое целое и число с плавающей точкой, соответственно. Для обозначения порядка big-endian используются те же метки, но в верхнем регистре — I , U , F . Ещё одна часто встречающаяся метка — это v , используемая для void . Число идущее следом за меткой обозначают количество используемых бит.
Если число стоит перед меткой, то метка обозначает массив: [42f32] — массив из 42 элементов типа float . Квадратные скобки группируют метки. Кроме массивов это может использоваться для обозначения структур ( [i32 i32] — структура с двумя полями типа int ) и объединений ( [u64|u64:f32] — long или указатель на float ).
Для обозначения указателей используется двоеточие. Например, u64:i32 — указатель на int , u64:v — указатель типа void , а u64:[i32 i32] — указатель на структуру.
Вооружившись этой информацией, немного усложним пример.
__declspec(dllexport) long sum(int vals[], int size) < long r = 0; for (int i = 0; i < size; i++) < r += vals[i]; >return r; >
App.java
В java-коде появилось сразу несколько новых элементов — Scope , Array и Pointer . Работая с нативным кодом, вам придётся оперировать off-heap данными, а значит придётся самостоятельно выделять память, самостоятельно освобождать и следить за актуальностью указателей. К счастью, есть Scope , берущий на себя все эти заботы. Его методы позволяют легко и удобно выделять неспецифицированную память, память под массивы, структуры и C-строки, получать указатели на эту память, а так же автоматически освобождать её после завершения блока try-with-resources и менять состояние созданных указателей так, чтобы обращение к ним приводило к исключению, а не падению виртуальной машины.
Чтобы посмотреть в работе структуры и указатели, усложним пример ещё немного.
#ifndef _ADDER_H #define _ADDER_H typedef struct < int x; int y; >Point; __declspec(dllexport) void move(Point*); #endif
mover.c
#include «mover.h» __declspec(dllexport) void move(Point *point) < point->x = 4; point->y = 2; >
App.java
Интерес здесь представляет то, как объявляется интерфейс структуры и как под неё выделяется память. Обратите внимание, что в ldl-объявлении появился новый элемент — значения в круглых скобках после меток. Это аннотация метки в сокращённой форме. Полная форма выглядела бы так: i32(name=x) . Аннотация метки позволяет соотнести её с методом интерфейса.
Прежде, чем переходить к обещанному в заголовке, осталось осветить ещё один способ взаимодействия с нативным кодом. Все предыдущие примеры вызывали нативные функции, но иногда нативному коду требуется вызывать java-код. Например, если мы хотим отсортировать массив с помощью qsort , нам понадобиться callback.
Легко заметить, что ldl-объявления, и так не особо простые для восприятия, быстро превращаются в зубодробительные конструкции. А ведь qsort — не самая сложная функция. Кроме того, в реальных библиотеках могут быть десятки структур и десятки функций, писать для них интерфейсы — дело неблагодарное. К счастью, обе проблемы легко решаются использованием утилиты jextract , которая сгенерирует всех необходимые интерфейсы на основе заголовочных файлов. Вернёмся к первому примеру и обработаем его этой утилитой.
jextract -L . -l adder -o adder.jar -t «com.example» adder.h
// импорт jextract’нутых «заголовочных» классов import static com.example.adder_h.*; public class Example < public static void main(String[] args) < System.out.println(add(3, 5)); >>
И используем полученный jar-файл для сборки и запуска java-кода:
javac -cp adder.jar Example.java java -cp .;adder.jar Example
Пока не особенно впечатляет, но позволяет понять принцип. А теперь проделаем то же самое с python37.dll (наконец-то!)
import java.foreign.Scope; import java.foreign.memory.Pointer; import static org.python.Python_h.*; import static org.python.pylifecycle_h.*; import static org.python.pythonrun_h.*; public class App < public static void main(String[] args) < Py_Initialize(); try (Scope s = Scope.newNativeScope()) < PyRun_SimpleStringFlags( s.allocateCString(«print(sum([23, 15, 4, 16, 42, 8]))n»), Pointer.nullPointer()); >Py_Finalize(); > >
jextract -L «C:Python37» -l python37 -o python.jar -t «org.python» —record-library-path C:Python37includePython.h
Компилируем и запускаем:
javac -cp python.jar App.java java -cp .;python.jar App
Поздравляю, ваше java-приложение только что загрузило в себя интерпретатор Python и выполнило в нём скрипт!

Больше примеров можно посмотреть в инструкции для первопроходцев.
Maven-проекты с примерами из статьи можно найти на GitHub.
P.S. API сейчас находится в стадии бурных изменений. В презентациях вышедших пару месяцев назад докладов легко увидеть код, который не будет компилироваться. Не застрахованы от этого и примеры из этой статьи. Если вы столкнётесь с этим, отправьте мне сообщение, постараюсь исправить.
Источник: habr.com