Я не понимаю, почему некоторые люди считают это бесполезным. На самом деле сценарий Java -> C -> Java очень распространен, когда вы начинаете программировать игры для Android:
- Приложение Android запускается с некоторого стандартного кода, написанного на Java (с использованием SDK)
- Запущен новый поток для запуска основной логики игры, которая написана на C / C ++ для повышения эффективности (и облегчения доступа к OpenGL ES )
- Код C / C ++ вызывает некоторые методы Java для требуемой функциональности
Причина, по которой необходимо использовать SDK (Java) , заключается в том, что большинство API-интерфейсов Android предоставляются только на Java! NDK (C / C ++) предоставляет только тонкую среду Linux (воспринимается как «Стандартная библиотека C» + «Стандартная библиотека C ++» + «Сокращенная версия системных библиотек Linux»). Например, если вы хотите интегрировать свое приложение с AdMob (Google Ads) или Биллинг в приложении (Google Payment) , или если вы хотите получить доступ к встроенной камере устройства, вы должны вызывать методы Java из игровой логики (которая написана на C / C ++!).
Java -> C Part
Написать класс Java. Объявите один метод native
:
$ ls -F1
classes/
jni/
src/
$ nano src/com/example/jcj/Test.java
Test.java:
package com.example.jcj;
public class Test {
public static void main(String[] args) {
doSomethingInC();
}
public static native void doSomethingInC();
public static void doSomethingInJava() {
System.out.println("Done something in Java!");
}
static {
System.loadLibrary("hello_jcj");
}
}
Вызовите «Java-компилятор» (javac
), а затем «Генератор заголовочных файлов и заглушек C» (javah
):
$ javac -sourcepath src -d classes src/com/example/jcj/Test.java
$ javah -classpath classes -d jni com.example.jcj.Test
$ ls -F1 jni/
com_example_jcj_Test.h
Реализация части C:
$ nano jni/com_example_jcj_Test.c
com_example_jcj_Test.c:
#include "com_example_jcj_Test.h"
#include <stdio.h>
/*
* Class: com_example_jcj_Test
* Method: doSomethingInC
* Signature: ()V
*/
JNIEXPORT void JNICALL
Java_com_example_jcj_Test_doSomethingInC(JNIEnv* env, jclass clazz)
{
printf("Done something in C!\n");
}
Скомпилируйте источник C (Windows):
> REM TODO: Add this!
Скомпилируйте источник C (Linux):
$ gcc -I{JAVA_HOME}/include
-shared \
-o libhello_jcj.so \
jni/com_example_jcj_Test.c
$ ls -F1
classes/
jni/
libhello_jcj.so*
src/
Скомпилируйте источник C (Mac OS X):
$ gcc -I${JAVA_HOME}/include \
-shared \
-o libhello_jcj.jnilib \
jni/com_example_jcj_Test.c
$ ls -F1
classes/
jni/
libhello_jcj.jnilib*
src/
Запустите приложение Java:
$ java -classpath classes com.example.jcj.Test
Done something in C!
C -> Часть Java
Поскольку вы запустили свою программу на Java (а не на C / C ++), JVM уже создана. Вам не нужно создавать еще одну во второй части (C -> часть Java), вам просто нужно повторно использовать уже созданную. Есть 2 способа сделать это:
- Используя указатель среды Java (
JNIEnv*
), предоставленный вызовом JNI из первой части (Java -> часть C)
- Используя указатель виртуальной машины Java (
JavaVM*
), сохраненный во время JNI_OnLoad()
(Ответ не закончен, и я закончу его позже. Если вам это нравится, пожалуйста, проголосуйте за поддержку. Спасибо!)
Ссылки