Registering JAVA function as Callback in C

3,157 views
Skip to first unread message

swap

unread,
Jul 27, 2010, 10:11:56 AM7/27/10
to android-ndk, karnik...@gmail.com
Hi group,
I am using NDK -r4.

I want to register callback function from JAVA to C so that whenever
some event triggers (asynchronously), C code can call/invoke JAVA
function.
I tried to simulate this scenario by using following code but during
compilation I got error messages listed below code. I have searched a
lot and could not succeed to get around this problem.


I started the thread from nativeMethod which wait for some time so
that, nativeMethod finishes its execution , then how can I call java
method?
I get, compilation errors for following code..
1. error: request for member 'GetEnv' in something not a structure or
union
2. error: request for member 'AttachCurrentThread' in something not a
structure or union
3. error: request for member 'DetachCurrentThread' in something not a
structure or union

Code in Question:

[Code]


#include <string.h>
#include <android/log.h>
#include <jni.h>
#include <stdio.h>
#include <stdlib.h> /* General Utilities */
#include <pthread.h> /* POSIX Threads */

JavaVM *m_vm;
jobject obj;
void message_function ( void *ptr );

JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
m_vm = vm;
return JNI_VERSION_1_4;
}

JNIEXPORT void JNICALL Java_com_company_pkg_swap_nativeMethod(JNIEnv
*env, jobject obj)
{

pthread_t thread1;
pthread_create (&thread1, NULL, (void *) &message_function, NULL); //
create thread
}


void message_function ( void *ptr )
{
int status;
JNIEnv *env;

sleep(5); // sleep for 5 sec ...
status = m_vm->GetEnv((void **) &env, JNI_VERSION_1_4); // I am
getting error here as
m_vm->AttachCurrentThread(&env, NULL);
jclass cls = (*env)->GetObjectClass(env, obj);
jmethodID mid =
(*env)->GetMethodID(env, cls, "callbackfromNative", "(Ljava/
lang/String;)V");
if (mid == NULL) {
m_vm->DetachCurrentThread();
return; // method not found
}

const char *pchar = "Hello This is string in C";
jstring jStr = NULL;
jStr = (*env)->NewStringUTF(env, pchar);

//printf("In C\n");
(*env)->CallVoidMethod(env, obj, mid,jStr);

m_vm->DetachCurrentThread();
pthread_exit(0);
}
[/Code]


How to make it working ???

Thanks in advance....
Note: I was referring this doc : http://android.wooyd.org/JNIExample/files/JNIExample.pdf

Warm Regards
Swap

fadden

unread,
Jul 27, 2010, 4:14:36 PM7/27/10
to android-ndk
On Jul 27, 7:11 am, swap <swapnil.bak...@gmail.com> wrote:
> JavaVM *m_vm;
...
>     status = m_vm->GetEnv((void **) &env, JNI_VERSION_1_4); // I am
> getting error here as

Change to:
(*m_vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4);
(and check the return value)

>     m_vm->AttachCurrentThread(&env, NULL);

Same thing:
(*m_vm)->AttachCurrentThread(vm, &env, NULL);

You seem to be using C-style for JNIEnv functions, and C++-style for
JavaVM functions.

swap

unread,
Jul 28, 2010, 5:51:39 AM7/28/10
to android-ndk
thanks for reply...
Ok, after changing as adviced, I am able to compile the code... I
have added logs to the code ...
Currently I am facing problem as application is crashing at line:
jclass cls = (*env)->GetObjectClass(env, obj);

Debug information from logcat:
07-28 15:09:58.053: WARN/dalvikvm(529): JNI WARNING: 0x43b8aa08 is not
a valid JNI reference
07-28 15:09:58.053: WARN/dalvikvm(529): in Ldalvik/system/
NativeStart;.run ()V (GetObjectClass)

I doubt on "obj" paratmeter passed to "jclass cls = (*env)-
>GetObjectClass(env, obj);"

[code ]
JavaVM *m_vm;
jobject obj;

JNIEXPORT void JNICALL Java_com_company_pkg_swap_nativeMethod(JNIEnv
*env, jobject obj)
{
obj = LObj; // write this line or comment it, No effect on
output ....

pthread_t thread1;
pthread_create (&thread1, NULL, (void *) &message_function, NULL); //
create thread
}

void message_function ( void *ptr )
{
int status;
JNIEnv *env;
jmethodID mid;
Log("before sleep");
sleep(5); // sleep for 5 sec ...
status = (*m_vm)->GetEnv(m_vm,(void **) &env, JNI_VERSION_1_4);
Log("attaching Current thread");
(*m_vm)->AttachCurrentThread(m_vm, &env, NULL);
if (env == NULL)
{
Log("failed to attached ");
}
Log("getting OBJ.. got class ");
jclass cls = (*env)->GetObjectClass(env, obj); //failing on this
line .....
if (cls != NULL)
{
Log(".. got class ");
mid =
(*env)->GetMethodID(env, cls, "callbackfromNative", "(Ljava/
lang/String;)V");
if (mid == NULL) {
Log("MID null");
(*m_vm)->DetachCurrentThread(m_vm);
return; // method not found
}
Log("got MID ");
}
else
{
Log("No class found ");
(*m_vm)->DetachCurrentThread(m_vm);
return; // class not found
}

Log("done with ID processing ");
const char *pchar = "Hello This is string in C";
jstring jStr = NULL;
jStr = (*env)->NewStringUTF(env, pchar);

Log("string alloc, calling Java method");
(*env)->CallVoidMethod(env, obj, mid,jStr);

(*m_vm)->DetachCurrentThread(m_vm);
//pthread_exit(0);

alan

unread,
Jul 28, 2010, 6:12:38 AM7/28/10
to android-ndk
if you are going to be using an object once a function returns you
must create a reference to it using either NewGlobalRef or NewWeakRef

swap

unread,
Jul 28, 2010, 6:31:07 AM7/28/10
to android-ndk
thanks for reply..
I am pretty new to the android and NDK,
can you please provide code snipnet.??

swap

unread,
Jul 28, 2010, 6:45:19 AM7/28/10
to android-ndk
Ok I have done that .. thanks a lot for help !!!

fadden

unread,
Jul 28, 2010, 5:20:41 PM7/28/10
to android-ndk
On Jul 28, 3:31 am, swap <swapnil.bak...@gmail.com> wrote:
> thanks for reply..
> I am pretty new to the android and NDK,
>  can you please provide code snipnet.??

This is a general JNI thing, not specific to Android or the NDK.

See the usual references:
http://java.sun.com/docs/books/jni/html/jniTOC.html
http://java.sun.com/javase/6/docs/technotes/guides/jni/spec/jniTOC.html
http://android.git.kernel.org/?p=platform/dalvik.git;a=blob_plain;f=docs/jni-tips.html;hb=HEAD

You will save time in the long run by stepping away from the keyboard
and reading through the documents. The last link ("Android JNI Tips")
calls out some of the common points of confusion.
Reply all
Reply to author
Forward
0 new messages