在JNI编程中,一般是在Java中调用C方法,用以实现Java向下传递信息。而反方向上的传递则有更多有趣的应用,例如利用C向Java实现异步通知,或触发事件,这种情况通常称为反射(Reflection)。
public class MyJni { static{ System.load("/home/smallfish/workspace/jni_test/java/libmyjni.so"); } public native String sayHello(String name); public native double sum(double x, double y); public static void main(String[] args) { MyJni myJni = new MyJni(); System.out.println(myJni.sum(1,1)); System.out.println(myJni.sayHello("Smallfish")+"!"); } public void c_max(int a, int b){ System.out.println("a = " + a + ", b = " + b); if(a > b){ System.out.println("a great than b!"); } else if (a == b) { System.out.println("a equal to b!"); } else { System.out.println("a less than b!"); } } }
以上为Java代码,下面是C代码。
#include "jni.h" #include "myjni.h" #include <stdio.h> JNIEXPORT jstring JNICALL Java_MyJni_sayHello( JNIEnv *env, jobject obj, jstring name){ const char *str = (*env)->GetStringUTFChars(env, name, NULL); char buf[512]; // obj = obj; printf("[%s:%d]\n", __func__, __LINE__); snprintf(buf, 512, "Hello, %s", str); (*env)->ReleaseStringUTFChars(env, name, str); jclass clazz = (*env)->FindClass(env, "MyJni"); jmethodID methodID = (*env)->GetMethodID(env, clazz, "c_max", "(II)V"); (*env)->CallVoidMethod(env, obj, methodID, (jint)20, (jint) 30); return (*env)->NewStringUTF(env, buf); } JNIEXPORT jdouble JNICALL Java_MyJni_sum(JNIEnv *env, jobject obj, jdouble a, jdouble b){ env = env; obj = obj; return a+b; }
运行结果:
解析:
1、定义MyJni类,引入libmyjni.so动态库,此库由C语言程序编译而来;
2、在MyJni类中声明两个Native方法,sayHello以及sum,由C代码实现;
3、定义main方法作为程序入口,定义c_max方法供C调用;
4、在main中调用sum方法,向C中的Java_MyJni_sum函数传入“1,1”并向Java环境返回“2.0”,由Java打印;
5、在main方法中首先向sayHello方法传入“Smallfish”,进入到C环境,在sayHello函数中首先打印函数名及行号,然后拼接新字符串“Hello, ”+ “Smallfish”。再调用Java中的c_max方法,向c_max传入20和30两个参数,在Java中打印“a = 20, b = 30”,“a less than b!”。
6、执行完c_max之后,回到C环境sayHello函数,然后sayHello函数向Java环境返回“Hello, Smallfish”,最后由Java打印。
转载请注明:OpenMind » 【JNI】C语言调用Java方法(反射)