细心的童鞋会发现这是上一篇的代码,更细心的童鞋会发现我做了一点小小的改变.
把#include <> 改为了#include ""
这可能是所有刚接触c编程的童鞋都会问的问题,参考:
http://blog.163.com/liujie_267/blog/static/87469217201042811538377/
所以我这里不管是用#include<> 还是使用#include""都是可以的.
java直接调用c代码的方式我们基本学会了,如何在c里面调用java代码呢?
调用JNIEnv的"FindClass"和"GetMethodID"找到 你想调用的那个方法.
这里我们调用的是最简单的无返回值,无参数类型的方法.
运行,崩溃了.
因为这里我的class名称传入错了,应该是"com/javalong/ndk/lession04/MainActivity"
使用"/"而不是"."
修改后,运行代码,成功调用.
这里使用的是最简单的无参数,无返回值方法.
下面我们来讲,如果调用有返回值,有参数,该怎么调用.
下面我把java方法改为
public String jniHandler(String tag,int i,int i2){
Log.e("TEST","invoke java method "+tag+i+i2);
return "SUCCESS";
}
现在有3个参数,有1个String返回值.那么我调用方法的时候就应该这么写了
jmethodID jmethod = (*env).GetMethodID(mainCls,"jniHandler","(Ljava/lang/String;II)Ljava/lang/String;");
原先是"()V"现在是"(Ljava/lang/String;II)Ljava/lang/String;"
怎么改成了这么一大串.
下面我们来看一张图片.
因为String对对象不是基本类型,所以String对应的符号应该是Ljava/lang/String; 千万不要落了最后的";",不是我打错了
最后一定要带上";".
至于其他基本类型就简单了,比如int 就是I
所以我上面的三个参数,最后简写为了"Ljava/lang/String;II"
并且返回值也是String,所以就是上面的写法.
我这里就不再深入去分析了,大家自己多练习下就明白了.
如果直接这么写
jstring result= (jstring) (*env).CallObjectMethod(instance, jmethod, "JNI Method Param", 1, 3);
运行后会报错,因为"字符串"是c里面的字符串,必须转成jstring后传入.如下:
jstring result= (jstring) (*env).CallObjectMethod(instance, jmethod, env->NewStringUTF("JNI Method Param"), 1, 3);
至于后面的int就不需要转化了.
运行代码,成功.
接下来我想把返回值result打印在logcat上,于是
__android_log_print(ANDROID_LOG_ERROR, "TEST",env->GetStringUTFChars(result, false));
"make project"
这是什么鬼?
好像是说我参数错了.查看下api
第二个参数必须是 常量.而我传入的是变量.所以不行.
对c有了解的童鞋,都应该知道printf("%s","字符串"); 这里的方式也是一样的.
所以需要改成.
__android_log_print(ANDROID_LOG_ERROR, "TEST", "%s",result);
晕 这样子还是会崩溃吖.于是我想到jstring是java的对象,我应该转化为c里面对应的字符串.
于是
__android_log_print(ANDROID_LOG_ERROR, "TEST", "%s",env->GetStringUTFChars(result, false));
终于可以了
所以学习ndk 还是要一步一个坑慢慢踩吖.....