Вызов собственных функций из Java без использования JNI (с использованием стековых манипуляций) - PullRequest
0 голосов
/ 23 марта 2012

В настоящее время я делаю Java-приложение, которое работает на встроенном devie (POS-терминале). Это устройство имеет виртуальную машину, специально созданную производителем.

Функции, взаимодействующие с оборудованием, определены в файлах C внутри этого виртуального источник машины (в профиле AFAIK).

Я не могу вызывать эти функции из своего java-кода, потому что, согласно официальной документации, виртуальная машина не поддерживает ни JNI, ни KNI, она поддерживает только «манипулирование стеком» как метод сопряжения C и Java-кода.

Насколько я мог видеть, аргументы нативных функций передаются с использованием стеков. Выдвижение аргументов перед вызовом функции и вставка их в функции (прототипы имеют пустые аргументы). Я думаю, что-то подобное должно быть сделано для вызова функций, может быть, что-то связанное со стеком вызовов?

Реальный вопрос в том, как мне соединить C и Java, используя «манипуляции со стеком»?

ОБНОВЛЕНИЕ: Пример вызываемой функции (код C). Печатает сообщение на экране устройства.

void PrintAt(void)
{
    Array msg = popStackAsType(Array);
    int y = popStack();
    int x = popStack();
    NativePrint(x,y,msg->bdata);
}

Ответы [ 2 ]

3 голосов
/ 23 марта 2012

Вы не можете реально ожидать этого, поскольку у вас нет контроля над стеком.JVM контролирует стек, и любые так называемые манипуляции со стеком - это просто мерзкий хак.Без JNI или чего-то подобного ваше лучшее решение, вероятно, состоит в том, чтобы выполнить код C в отдельном процессе и использовать некую форму IPC для связи с ним.

1 голос
/ 23 марта 2012

Поскольку вы сказали "прототипы имеют пустые аргументы", я предполагаю, что у вас есть нативные методы Java, которые вы можете вызывать, но они используют верхние элементы стека в качестве аргументов, фактически не потребляя их.Примерно так:

class Native {
   native static void doSomething() {
      // do something with stack[sp] as an int and stack[sp - 1] as
      // an object reference, but do not modify sp.
   }
}

Если вы написали необработанный байт-код, вы можете просто выдвинуть аргументы, затем выполнить invokestatic, а затем щелкнуть.Если вам нужен способ сделать это, похожий на Java, я думаю, это должно сработать:

class Dummy {
   static void doSomething(int a, Object b) {
      Native.doSomething();
   }
}

Тогда a и b уже будут в стеке от вызова к Dummy.doSomething()и может быть проверено встроенным методом.

Редактировать:

Вы действительно имеете в виду, что аргументы выталкиваются внутри встроенных функций?В этом случае не должно быть возможности вызывать их из любого Java или кода байт-кода, потому что верификатор байт-кода захлебнется: он проверяет, что каждый путь выполнения через функцию оставляет стек того же размера, что и началсяи он не может знать о скрытых всплывающих окнах в нативном коде, которые напрямую изменяют стек.

...