Learning about JNI in Android (vi) Implementation of the method of registration in JNI

Source: Internet
Author: User

In the previous example, we would find that when a method is defined in a Java class, such as the following:

public class Paramtransfertest {public static int testval = 1;public native void Changetestval ();

In the corresponding JNI layer, the header file generated by Javah and its corresponding C file must have a method name such as the following:

jniexport void Jnicall Java_com_lms_jni_paramtransfertest_changetestval

The method name has to be this, based on some of the JNI naming conventions we mentioned in the previous article, but is it necessary to do so, much trouble.

(Tips:jniexport and Jnicall is a JNI compilation of the Windows platform, on Android phones, in fact, can not do these two keyword)

The answer is, of course, negative.

In the previous example, why must the method name implemented at the JNI layer conform to a certain naming convention? This is due to the fact that we do not provide a link between the JNI layer method and the Java-side approach, or a corresponding relationship, and because of the lack of such a corresponding relationship of our own definition, the NDK at compile time, the operating system at the time of interpretation, they must develop a series of rules, And through this rule to find the appropriate method. Otherwise, suppose you arbitrarily define a method name, I casually define a method name, how can others know that these two are corresponding? No rules inadequate surrounding area, so ...

So, assuming we don't want to write these long, smelly methods, we have to give them a corresponding relationship, and JNI actually provides this set of mechanisms, and this blog post lets us see how this is done in Android.

In fact, the implementation and loading of the methods involved in the JNI layer in the underlying source code of Android are basically done through the mechanism of this method of registration, including the implementation of the log mentioned in our previous article.

In the jni.h file, the structure of the jninativemethod is provided, such as the following:

typedef struct {    const char* name;<span style= "White-space:pre" ></span>//java-side method name    Const char* Signature;<span style= "White-space:pre" ></span>//method signature    void* Fnptr;<span style=       " White-space:pre "></SPAN>//JNI layer function pointer} jninativemethod;

Jninativemethod This structure, storage is the Java End method and the JNI layer method of a corresponding relationship, which has three fields, meaning, we look at the gaze is clear.

Next, we'll look at a little demo to see how to implement the Register function in JNI and then load it into use by the DVM.

1) Define a native method on the Java side, such as the following:

public class Dynreg {public native static String SayHello ();}

2) Create the corresponding C file in the JNI layer, this time, we do not need to generate the use of Javah generated header files and so on, and then copy the method name, such as the following:

Jstring Say_hello (JNIEnv *e, Jobject j) {return (*e)->newstringutf (E, "Say hello from dynamic register");}

We don't have to follow the traditional JNI programming nomenclature, we can customize the name of the method we want, like Say_hello and so on.

4) Use the JNINATIVEMETHOD structure to create a corresponding relationship, such as the following:

Static Jninativemethod mehtod_table[] = {{"SayHello", "() ljava/lang/string;", (void*) Say_hello},};

This is an array of structures, corresponding to several methods, in this example, we have only one method, so there is only one element that we can see:

4.1) "SayHello", corresponding to the Java-side method

4.2) "() ljava/lang/string", corresponding to its method signature

4.3) (void*) Say_hello, corresponding to the C method we implemented above

5) apply this corresponding to the DVM in the Jni_onload method, such as the following:

static int Registernativemethods (jnienv* env, const char* classname,jninativemethod* methods, int nummethods) {Jclass CLA Zz;clazz = (*env)->findclass (env, ClassName), if (clazz = = NULL) {return jni_false;} if ((*env)->registernatives (env, Clazz, methods, Nummethods) < 0) {return jni_false;} return jni_true;} Jint jni_onload (javavm* JVM, void* reserved) {jnienv* env = null;jint result = -1;if ((*JVM)->getenv (JVM, (void**) & ; env, jni_version_1_4)! = JNI_OK) {return result;} Registernativemethods (env, "Com/lms/jni/dynreg", Mehtod_table, Nelem (mehtod_table)); return jni_version_1_4;}

Briefly speaking about this process, when these C files are compiled into the corresponding so files, the Jni_onload method in the corresponding class is called when the Java side uses System.loadlibrary to load the so library. This is actually the concept of a callback function equivalent to some interface, in the load, we can be defined above the Jninativemethod array, by calling Jnienv* 's Registernatives method, the method in this array to the JNIENV, In the bottom-level implementation, when the DVM calls the corresponding native method, will be based on our there is no register to jnienv* to find the corresponding method, assuming found, directly run, assuming not found, jnienv* will continue to be based on the traditional JNI method naming norms to find the original long and smelly method, assuming that the method has not been found, will be an error.

5.1) call Registernativemethods, pass in the corresponding class name "Com/lms/jni/dynreg", there are method table method_table, Method table in the number of methods, Nelem is a macro defined, such as the following:

# define Nelem (x) ((int) (sizeof (x)/sizeof ((x) [0]))

5.2) in the Registernativemethods method, according to the class name, find the corresponding class, the class, method and method number call Registernatives method register to jnienv*.

6) Declare our newly added class dynreg.c in the Android.mk file, such as the following:

Local_path: = $ (call My-dir) include $ (clear_vars) Local_module: = com_lms_jni_hwdemolocal_src_files: = hwdemo.c jnitest.c ParamTransferTest.cDynReg.cLOCAL_LDLIBS + =-lloginclude $ (build_shared_library)

7) Finally use this method in the Java side, such as the following:

Tv.settext (Dynreg.sayhello ());

8) Results such as the following:


The method of using the Register function in JNI to communicate with each other in the JNI layer and Java layer is almost the same here, and with this method, does it look more comfortable when writing a C + + method?

End.

Learning about JNI in Android (vi) Implementation of the method of registration in JNI

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.