Запустите JavaVM из AutoIt - PullRequest
       38

Запустите JavaVM из AutoIt

0 голосов
/ 15 февраля 2020

Я пишу программу запуска EXE для приложения Java с использованием AutoIt. Он отлично работает при запуске Java через ShellExecute, но по нескольким причинам я хотел бы вызвать его через DLL (чтобы не создавать отдельный процесс)

Но я не могу понять, как предоставить необходимую структуру DLL для вызова. Проблема в том, что это вложенная структура, где вложенный элемент представляет собой массив указателей char *.

Документация JDK содержит пример: https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/invocation.html#JNI_CreateJavaV

JavaVMInitArgs vm_args;
JavaVMOption options[4];

// Defining the array and filling the elements is the part I don't know how to do with AutoIt
// (Don't mind the content here)
options[0].optionString = "-Djava.compiler=NONE";           /* disable JIT */
options[1].optionString = "-Djava.class.path=c:\myclasses"; /* user classes */
options[2].optionString = "-Djava.library.path=c:\mylibs";  /* set native library path */
options[3].optionString = "-verbose:jni";                   /* print JNI-related messages */

vm_args.version = JNI_VERSION_1_2;
vm_args.options = options;
vm_args.nOptions = 4;
vm_args.ignoreUnrecognized = TRUE;

res = JNI_CreateJavaVM(&vm, (void **)&env, &vm_args);

И определения двух структур:

typedef struct JavaVMOption {
    char *optionString;
    void *extraInfo;
} JavaVMOption;

typedef struct JavaVMInitArgs {
    jint version;

    jint nOptions;
    JavaVMOption *options;
    jboolean ignoreUnrecognized;
} JavaVMInitArgs;

После просматривая несколько форумов, я нашел пример кода, который должен запускать JavaVM через DLL (в процессе):

Local $optionArray[2]
$optionArray[0] = "-cp MyApp.jar"
$optionArray[1] = "MyMain"
$env = 0
$option = DllStructCreate("struct;char* optionString;ptr extraInfo;endstruct")
$vmInitArgs = DllStructCreate("struct;LONG version;LONG nOptions;ptr options;BOOLEAN ignoreUnrecognized;endstruct")

; Not sure if this is correct
DllStructSetData($option, "optionString", $optionArray)

DllStructSetData($vmInitArgs, "version", 0x00010008)
DllStructSetData($vmInitArgs, "nOptions", 2)
DllStructSetData($vmInitArgs, "options", DllStructGetPtr($option))
DllStructSetData($vmInitArgs, "ignoreUnrecognized", 1)
Local $handle = DllOpen($dllPath)
$res = DllCall($handle, "INT", "JNI_CreateJavaVM", "ptr*", $env, "ptr", DllStructGetPtr($vmInitArgs))
ConsoleWrite("*** Error: " & @error & @CRLF)
ConsoleWrite("*** Result: " & $res[0] & @CRLF)
DllClose($handle)

Код @error всегда равен 0, но $ res [0] содержит код ошибки (-3), который в теории указывает, что версия JNI неверна, но большинство найденных ответов указывают на то, что это также может означать, что структура JavaVMInitArgs была заполнена неправильно. И учитывая тот факт, что JavaVMInitArgs делает некоторые вещи с указателями, я предполагаю, что способ, которым я заполняю его из AutoIt, не верен.

Я также попытался вызвать DllStructSetData с индексным номером, а не с «именем члена». Я также пытался вызвать DllStructCreate без маркеров "struct / endstruct" и без имен членов.

У меня нет опыта программирования на C / C ++, поэтому я затрудняюсь с отображением информации из Java документов в AutoIt.

Итак, как я могу инициализировать JavaVM из AutoIt, используя JNI_CreateJavaVM?

Следующим шагом будет запуск программы Java. Для этого мне нужно было бы динамически вызвать findClass(), чтобы получить указатель на основной класс, а затем вызвать его через JNI.

Если , я могу правильно загрузить JVM, это должно быть чем-то вроде

$aRET = DllCall($env, "str", "FindClass", "str", "ClassName")

Возможно ли то, что я пытаюсь сделать вообще? Или я должен использовать C / C ++ для этого? (Я бы тоже принял этот ответ)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...