call a java void from android ndk

Started by
11 comments, last by ver_1_alpha 8 years, 4 months ago

		AnsiString ahue = "";
		if ( (apply_to->scriptlen > 0) || (apply_to->script != NULL)) ahue = apply_to->script;
		JNIEnv * env = NULL;
		int status;
		status = ANDROID_ENVIROMENT->GetEnv((void **)&env, JNI_VERSION_1_6);
		if(status < 0) ALOG("CANT FIND ENVIROMENT");
		ANDROID_ENVIROMENT->AttachCurrentThread(&env, NULL);
		if(status < 0) ALOG("CANT ATTACH THREAD");
		jstring jstr = env->NewStringUTF(ahue.c_str());
		jclass activityClass = env->FindClass("com/example/wirednavalbattle/MainActivity");
		if (activityClass == NULL) ALOG("CLASS IS NULL");
		jmethodID MemoScript = env->GetMethodID(activityClass, "ScriptMemo", "(Ljava/lang/String;)V");
if (MemoScript == NULL) ALOG("WRONG METHOD");

		env->CallVoidMethod(activityClass, MemoScript, jstr); <-- it breaks here

java code

	public void ScriptMemo(String text)
	{
		finish();  

	}

how i init ANDROID_ENVIROMENT var


JNIEXPORT void JNICALL Java_com_example_wirednavalbattle_GameLibJNIWrapper_PSetEnviroment(JNIEnv * env, jclass cls, jint str)
{
	 JavaVM* jvm;
	 env->GetJavaVM(&jvm);
	MakeEnv(jvm); //cal in the same h file
}

void MakeEnv(JavaVM * jvm)
{
	SetAppEnviroment(jvm); //call in diffrent h file
}

void SetAppEnviroment(JavaVM* jvm)
{
ANDROID_ENVIROMENT = jvm;
}





//now in java when i have my class extends Activity

i overrride onCreate function and place there

THE_RENDER_WRAPPER.NMBSetEnv(0); //set enviroment this calls the function on top

error is:

12-16 02:05:36.140: A/libc(16315): Fatal signal 11 (SIGSEGV) at 0x000002d3 (code=1), thread 16315 (irednavalbattle)

12-16 02:05:36.250: I/DEBUG(137): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
12-16 02:05:36.250: I/DEBUG(137): Build fingerprint: 'orange_pl/ST26i_1267-4750/ST26i:4.1.2/11.2.A.0.31/07_96g:user/release-keys'
12-16 02:05:36.250: I/DEBUG(137): pid: 16315, tid: 16315, name: irednavalbattle >>> com.example.wirednavalbattle <<<
12-16 02:05:36.250: I/DEBUG(137): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 000002d3

12-16 02:05:36.520: I/DEBUG(137): #00 pc 00069ff0 /system/lib/libdvm.so (dvmGetVirtualizedMethod(ClassObject const*, Method const*)+75)

12-16 02:05:36.520: I/DEBUG(137): #01 pc 0004cf7d /system/lib/libdvm.so
12-16 02:05:36.520: I/DEBUG(137): #02 pc 0005c3d8 /data/data/com.example.wirednavalbattle/lib/libgame.so (_JNIEnv::CallVoidMethod(_jobject*, _jmethodID*, ...)+60)

12-16 02:05:36.530: I/DEBUG(137): be99a154 537a03dc /data/data/com.example.wirednavalbattle/lib/libgame.so (_JNIEnv::CallVoidMethod(_jobject*, _jmethodID*, ...)+64)

looks more like bad address taken, i have no idea why ;x

Advertisement


		env->CallVoidMethod(activityClass, MemoScript, jstr); <-- it breaks here

The first argument to CallVoidMethod() is the instance you are calling it on, not the class.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

i dont understand., i can't find any info of the list of CallVoidMethod parameters.

You just get the jclass of your main activity and try to send it in. That's not possible. You need the jobject of your main activity (the actual instance, not just the class type)

To get that, you need to pass it down to your C++ code somehow, you can't get it with JNI code only.

I do it by passing down the activity as an argument when initializing the JNI part of my application

Here is the page I use when I wonder about any JNI call: http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html

But remembering that when using it in C++, the first "env" argument is removed on all calls.

Note that you can call a static void method the way you are attempting (although you would need to use CallStaticVoidMethod()).

A non-static method always requires a an object reference to satisfy the implicit this argument.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

this is bulls***, i dont even know what kind of jobject is in java, i stop implementing text editor for script editing in java (i just wanted a stupid text field and retreive its text)

its way easier for me to add {} () ; <> = buttons as new keyboard layout for my opengl text editor rather that screwing with cesspol called java


this is bulls***, i dont even know what kind of jobject is in java

All java objects are derived from java.lang.Object, so you can treat jobject as pointer to most common base.

And you're too c++ -centric. What you got by calling env->FindClass() is something similar to c++'s typeinfo.

Yes, it's also object, but that's the instance of typeinfo class, and not the instance of MainActivity class.

If your native methods doesn't belong to main activity class, you'll have to pass main activity instance explicitly to that native method.

If it was main activity's method, you'd get reference to activity instance as second argument to native method ("this" pointer).

Note that there's other possible causes to crash.

If you're calling that method not from Java thread, but from native thread, then class might be not found, since android will try search desired class from class loader, found by tracing stack.

Also take note, that if FindClass() failed, it will raise exception. Exception state should be explicitly checked and cleared, otherwise jni code will crash on next call to java.


i dont even know what kind of jobject is in java, i stop implementing text editor for script editing in java ... its way easier for me to add {} () ; <> = buttons as new keyboard layout for my opengl text editor
The problem is not with Java. It is endemic to software development and to learning new systems generally.

If you know what piece to add it is quick and easy. Adding a simple piece of code to a well-written system is generally straightforward. Adding a new piece of data to a well-written system is also generally straightforward.

But if you don't know those details, adding a new piece can be very difficult. That is part of the learning curve.

It is hard before you've mastered it and when using poorly-architected systems. Once you've mastered the system you can start building well-architected systems, and convert your poorly-architected systems into better ones. And once you've got those, extending it becomes quick easy.

It's also worth pointing out that Android's NDK support isn't really designed for writing pure C++ applications (although there is minimal support for that use-case).

It's really meant to allow Java applications to call out to native code. You'll generally find you have a much easier time of things if you bootstrap everything with a Java app, and then handoff to native for the game logic and any performance critical areas like rendering and physics.

This means that control always flows from Java -> C++, and you almost never end up needing to call back up into Java methods. All your JNI methods can be neatly encapsulated as static methods in a wrapper class, and like becomes a much happier place.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

yeah but i am even unable to call public static void ShowTextEditor()

{

javacrap here <- cannot call nonstatic from static some thing like that

}

This topic is closed to new replies.

Advertisement