- PVSM.RU - https://www.pvsm.ru -

Встраиваем интерпретатор Python в java-приложение с помощью проекта Panama

Пару дней назад увидел твит Брайана Гетца, но только сегодня дошли руки поиграться с примерами.

image [1]

Про это и хочу кратко рассказать.

О проекте Panama [2] на Хабре уже писали [3], поэтому просто покажу пару простых примеров того, как можно применить native binder.

Прежде всего вам понадобится компилятор C. Если вы используете Linux или MacOS, то он у вас уже есть. Если Windows, то придётся сначала установить Build Tools for Visual Studio 2017 [4]. И, конечно же, вам потребуется OpenJDK с поддержкой «Панамы». Получить его можно либо сборкой ветки «foreign» соответствующего репозитория [5], либо загрузкой Early-Access билда [6].

Начнём с минимального примера — простой функции складывающей два числа:

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:Python37includePython.h

Компилируем и запускаем:

javac -cp python.jar PythonMain.java
java -cp .;python.jar PythonMain

Поздравляю, ваше java-приложение только что загрузило в себя интерпретатор Python и выполнило в нём скрипт!

image

Больше примеров можно посмотреть в инструкции для первопроходцев [7].

Автор: sergey-gornostaev

Источник [8]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/java/308963

Ссылки в тексте:

[1] Image: https://twitter.com/BrianGoetz/status/1096050570576703490

[2] проекте Panama: https://openjdk.java.net/projects/panama/

[3] уже писали: https://habr.com/ru/company/jugru/blog/310014/

[4] Build Tools for Visual Studio 2017: https://visualstudio.microsoft.com/ru/downloads/

[5] соответствующего репозитория: http://hg.openjdk.java.net/panama/dev/

[6] Early-Access билда: http://jdk.java.net/panama/

[7] инструкции для первопроходцев: https://hg.openjdk.java.net/panama/dev/raw-file/c359a9e944de/doc/panama_foreign.html

[8] Источник: https://habr.com/ru/post/440470/?utm_campaign=440470