欢迎转载!转载时请注明出处:http://write.blog.csdn.net/postedit/8182856
有一周多没有更新博客了,估计很多人都在心里问,博主最近在干吗啦!都没有到发表新的博文了,由于上上周的时候,出去失业状态,然后再群里自荐,然后就有朋友给我推荐了工作,不记得具体是那个了,在此感谢他,也感谢那么多的朋友们给我的肯定...非常感谢!
JNI估计大部分朋友听到这个东西就会怕~ 如果没有接触过,却是搞的你非常的头大...好了废话不多说了...开始吧
首先来接触一些知识点:
1、基本数据类型对应该关系表:
其实仔细看看发现就是对应java类型的首字母拉, Boolean比较特殊, 对应的是 Z , Long 对应J
2、Java 方法映射到C中的签名:(介绍四个方法对应的签名)
public void test(){} ()V
public void test1(int i){} (I)V
public int test2(){ return 1;} ()I
public int test3(int i) { return i;} (I)I
3、引用数据类型:比较麻烦点,以“L”开头,以“;”结束,中间对应的是该类型的路径
如:String : Ljava/lang/String;
Object: Ljava/lang/Object;
自定义类 Cat 对应 package com.duicky;
Cat:Lcom/duicky/Cat;
4、数组表示: 数组表示的时候以“[” 为标志,一个“[”表示一维数组
如:int [] :[I
Long[][] : [[J
Object[][][]:[[[Ljava/lang/Object;
5、查看JDK生成的签名写一个测试类,有如下方法:
public void test(){}
public void test1(int i){}
public int test2(){ return 1;}
public int test3(int i) { return i;}
public Cat test4(Cat c){ return new Cat();}
public Object test5(int [] a){ return null;}
public int[][] test5(long [][] b){ return null;}
public void test6(Object[][][] b){}
打开Cmd 命令行,cd 到 生成测试类打开Cmd 命令行,cd 到 生成测试类 的 Class 目录:
Cd 到相对应的 文件夹
输入命令: javap –s 加上你要查看方法签名的类 名
如: javap –s Test 结果就显示出我们想要的签名了
6、Java调用C方法:
第一步:编写native方法:
private native int fromC();
第二步:编写JNI:(我是直接用的cocos2dx中的main.cpp方法,然后写到extern"C"{}中的喔~ 为了易看,其他代码省略)
using namespace cocos2d;
using namespace cocos2d::extension;
using namespace std;
extern "C"
{
jint Java_potter_back_MyHelloWorld_fromC(){
return 222;
}
第三步:调用native方法
package potter.back;
public class Main {
public static void main(String[] args) {
System.out.println("fromC++"+new Main().fromC());
}
private native int fromC();
}
7、C调用Java方法:后面这样放着好看点,就用后面这种方式排版吧~
package potter.back;
public class Main {
public static void main(String[] args) {
new Main().fromJava();
}
private native int fromJava();
}
class Potter {
public void fromJava(String msg){
System.out.println("From Android");
}
}
编写JNI方法
void Java_potter_back_MyHelloWorld_fromJava(JNIEnv* jniEnv, jobject thiz)
{
//映射类
jclass Potter=jniEnv->FindClass("potter/back/Potter");
//映射构造方法
jmethodID construction_id = jniEnv->GetMethodID(Potter,"<init>", "()V");
//创建对象
jobject mPotter = jniEnv->NewObject(obj_class,construction_id);
//映射对象方法
jmethodID fromJava=jniEnv->GetMethodID(Potter,"fromJava","(Ljava/lang/String;)V");
//调用Java对象mPotter的fromJava方法
jniEnv->CallVoidMethod(mPotter, fromJava,jstrMSG);
}
8、通过JNI传递Java对象:
public class Main {
public static void main(String[] args) {
new Main().javaObjectToC();
}
public void javaObjectToC(){
//通过C++调用Java中的方法,然后传递Person对象
Person p=new Person(24);
cCallJava(p);
System.out.println("p's age="+p.age);
}
public native void cCallJava(Person p);
}
class Person{
public int age;
public Person(int age){
this.age=age;
}
public void walk(){
System.out.println("Person can walk");
}
}
第二步:
void Java_potter_back_MyHelloWorld_fromJava(JNIEnv* jniEnv, jobject thiz,jobject obj)
{
//获得Person类:获得obj对象的句柄
jclass cls =jniEnv->GetObjectClass(obj);
jfieldID fid = jniEnv->GetFieldID(cls,"age", "I");
jmethodID mid = jniEnv->GetMethodID(cls, "walk", "()V");
int value = jniEnv->GetIntField(obj, fid);
jniEnv->SetIntField(obj, fid, 6);
jniEnv->CallVoidMethod(obj, mid);
}
第三步:运行
Person can walk
p's age=6 //此值被修改了喔~ 出事为24,然后再JNI中设置成6了喔
9、Java通过JNI传递C++对象:(这种方法,我找了n多的资料,都没有找到对应的,不过利用7小标题,这种方式是可以进行数据传输的) 如果有朋友知道有更加直接的办法请告诉我...万分感谢~
感谢大家阅览我的博文,希望也能看到大家留下的脚印...呵呵!
如果讲述得有误,或者不对的地方,还望各位指出!
参考资料:http://www.cnblogs.com/luxiaofeng54/archive/2011/08/18/2143977.html