Легко Вызывать Методы Java Из Собственного Кода.

Существует довольно много приложений для Android, сочетающих в себе код C++ и Java. Где Java действует как оболочка/слой, а C++ выполняет всю грязную работу.

Пожалуй, ярким примером являются игры.

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

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

Потом еще нужно преобразовать эти параметры к нужному типу.

Стандартный пример из туториалов:

  
  
  
  
  
   

long f (int n, String s, float g);

Строка подписи для этого метода будет (ILjava/язык/строка;F)J .

Удобно ли вам все это помнить? Как насчет преобразования C-строк в jstring? Нет мне.

Я хочу написать:

CallStaticMethod<long>(className, “f”, 1, 1.2f);



Постановка задачи

Для начала давайте поймем, что нам нужно.

По сути, это четыре вещи:

  1. Метод вызова;
  2. Вам необходимо извлечь строку подписи из параметров.

    Да-да, вот этот (ILjava/lang/String;F)J;

  3. Преобразовать параметры к нужному типу;
  4. Верните тип данных, который хочет видеть пользователь нашего класса.

Собственно, это все.

Кажется, это просто.

Давайте начнем?

Вызов метода

Теперь стоит отметить, как мы будем вызывать нашу функцию-обертку.

Так как параметров может быть разное количество (от нуля и больше), то в стандартной библиотеке нужна функция типа print, но так, чтобы было удобно извлекать тип параметра и сам параметр.

В C++11 представлены шаблоны с переменным числом вариантов.

Мы будем использовать их.



template <typename MethodType, typename. Args> MethodType CallStaticMethod(Args. args);



Делаем подпись

Сначала нам нужно получить строку, указанную в документации для этого типа.

Есть два варианта:

  1. Мы используем typeid и цепочку if.else. Это должно выглядеть примерно так:

    if (typeid(arg) == typeid(int)) return “I”; else if (typeid(arg) == typeid(float)) return “F”;

    И так для всех нужных вам типов.

  2. Мы используем шаблоны и их частичные типизации.

    Способ интересен тем, что у вас будут функции в одной строке и не будет лишних сравнений типов.

    Причём всё это будет на этапе создания шаблона.

    Все будет выглядеть примерно так:

    template <typename T> std::string GetTypeName(); // int template <> std::string GetTypeName<int>() { return “I”; } // string template <> std::string GetTypeName<const char*>() { return “Ljava/lang/String;”; }

В нашем есть два способа создания строки подписи: рекурсивный и через массив.

Давайте сначала посмотрим на рекурсивный вызов.



void GetTypeRecursive(std::string&) { } template <typename T, typename. Args> void GetTypeRecursive(std::string& signatureString, T value, Args. args)

Теги: #C++ #jni #android ndk #templates #C++ #Разработка для Android

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.