Eu sou muito novo para JNI e estou tentando descobrir como certas coisas funcionam antes de eu portar meu código C ++ iOS para ele. Consegui obter uma das amostras do NDK em funcionamento no Android Studio e vejo como o Java é capaz de chamar funções do C ++.
Eu tenho procurado por aí e tendo pedaços de código, mas não consegui fazê-lo funcionar na minha implementação específica.
Apenas para testar como as coisas funcionavam, eu configurei uma function simples de log de texto em java, e estou tentando chamá-lo do meu código nativo, mas acabei encontrando problemas.
Aqui está minha function Java:
public static void log(String s){ Log.d("Native", s); }
E C ++:
void Log(std::string s){ JNIEnv *env; g_JavaVM->GetEnv((void**)&env, JNI_VERSION_1_6); jstring jstr1 = env->NewStringUTF(s.c_str()); jclass clazz = env->FindClass("com/android/gl2jni/GL2JNILib"); jmethodID mid = env->GetStaticMethodID(clazz, "log", "(Ljava/lang/String;)V"); jobject obj = env->CallStaticObjectMethod(clazz, mid, jstr1); }
Pelo que vi com exemplos diferentes, isso deve funcionar, mas gera um erro:
29835-29849/com.android.gl2jni A/libc﹕ Fatal signal 11 (SIGSEGV) at 0x00000000 (code=1), thread 29849 (Thread-17371)
Estou esquecendo de algo?
EDITAR:
Eu mudei para GetStaticMethodID. Mas depois de registrar o progresso da function, descobri que a linha que falha é:
g_JavaVM->GetEnv((void**)&env, JNI_VERSION_1_6);
O que eu acho é que g_JavaVM está definido como static JavaVM* g_JavaVM = NULL;
e depois nunca mais tocou. Eu estou supondo que preciso definir essa variável, mas como?
Parte do meu problema foi que eu não inicializei o JavaVM. A outra parte era que eu estava usando C ++, mas eu estava tentando usar as funções C.
O código de trabalho é:
Java:
public static void log(String s){ Log.d("Native", s); }
C ++:
void Log(std::string s){ JNIEnv *env; g_JavaVM->GetEnv((void**)&env, JNI_VERSION_1_6); jstring jstr1 = env->NewStringUTF(s.c_str()); jclass clazz = env->FindClass("com/android/gl2jni/GL2JNILib"); jmethodID mid = env->GetStaticMethodID(clazz, "log", "(Ljava/lang/String;)V"); jobject obj = env->CallStaticObjectMethod(clazz, mid, jstr1); } //In some initialization function with Environment variable env->GetJavaVM(&g_JavaVM);
Espero que isso possa ajudar outras pessoas com o mesmo problema.
http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html
GetStaticMethodID
jmethodID GetStaticMethodID (JNIEnv * env, jclass clazz, const char * nome, const char * sig);
Retorna o ID do método para um método estático de uma class. O método é especificado pelo seu nome e assinatura.