Встраиваем интерпретатор Python в java-приложение с помощью проекта Panama
Пару дней назад увидел твит Брайана Гетца, но только сегодня дошли руки поиграться с примерами.
Про это и хочу кратко рассказать.
О проекте Panama на Хабре уже писали, поэтому просто покажу пару простых примеров того, как можно применить native binder.
Прежде всего вам понадобится компилятор C. Если вы используете Linux или MacOS, то он у вас уже есть. Если Windows, то придётся сначала установить Build Tools for Visual Studio 2017. И, конечно же, вам потребуется OpenJDK с поддержкой «Панамы». Получить его можно либо сборкой ветки «foreign» соответствующего репозитория, либо загрузкой Early-Access билда.
Начнём с минимального примера — простой функции складывающей два числа:
adder.h
#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) {
return a + b;
}
Example.java
// импорт jextract'нутых "заголовочных" классов
import static com.example.adder_h.*;
public class Example {
public static void main(String[] args) {
System.out.println(add(3, 5));
}
}
Компилируем в DLL
cl /LD adder.c
Используем утилиту jextract
для генерации java-интерфейса на основе заголовочного файла:
jextract -L . -l adder -o adder.jar -t "com.example" adder.h
И используем полученный jar-файл для сборки и запуска java-кода:
javac -cp adder.jar Example.java
java -cp .;adder.jar Example
Пока не особенно впечатляет, но позволяет понять принцип. Теперь попробуем использовать python37.dll.
PythonMain.java
import java.foreign.Libraries;
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 PythonMain {
public static void main(String[] args) {
Py_Initialize();
try (Scope s = Scope.newNativeScope()) {
PyRun_SimpleStringFlags(s.allocateCString(
"print(sum([33, 55, 66]))\n"),
Pointer.nullPointer());
}
Py_Finalize();
}
}
Генерируем интерфейсы:
jextract -L "C:\Python37" -l python37 -o python.jar -t "org.python" --record-library-path C:\Python37\include\Python.h
Компилируем и запускаем:
javac -cp python.jar PythonMain.java
java -cp .;python.jar PythonMain
Поздравляю, ваше java-приложение только что загрузило в себя интерпретатор Python и выполнило в нём скрипт!
Больше примеров можно посмотреть в инструкции для первопроходцев.