刚开始一直没有找到该系列的第五篇博客,郁闷的要死,本打算重写的,看来没必要了.那这一篇就相当于小结第五篇和第六篇使用的样例.
所有的NDK都是在Linux系统下开发的,jni C或者CPP文件这一篇开始是在windosws7 VC6.0中开发的.所以下面的新建Android项目之类的都是在我的Ubuntu12.04中进行的.
<1> : 首先新建一个Android工程androidjnicppdemo1,包名package com.org.androidjnicppdemo1;
<2> : 在工程下新建一个jnipack的包,在这个包下新建一个JniClass.java的文件,build后(一定要先生成class文件),在工程根目录下新建一个jni,让后让终端进入jni文件目录下执行:
javah -classpath ../bin/classes jnipack.JniClass
把生成的jnipack_JniClass.h名改为JniClass.h,不要包名.
<3> : 上面的操作和以前的没什么区别.让后启动VC6.0,VC6.0耗内存非常少,所以这个很快捷.新建一个console工程就可以了,然后新建一个JniClass.h的头文件和JniClass.cpp文件,将上面生成的JniClass.h文件内容拷贝VC同名下的文件中,然后具体实现在JniClass.cpp文件中实现.
截图如下:JniClass.c代码如下:
#include "JniClass.h"jclass mClass;jobject mObject;jmethodID mMethodID;jmethodID mMethodAddID;jfieldID mFieldID;JNIEXPORT void JNICALL Java_jnipack_JniClass_nativeinit(JNIEnv *env, jobject thiz){ jclass cls=(*env)->GetObjectClass(env,thiz); mClass=(jclass)(*env)->NewGlobalRef(env,cls);// mClass=(jclass)(*env)->FindClass(env,"jnipack.JniClass"); mObject=(jobject)(*env)->NewGlobalRef(env,thiz); mFieldID=(*env)->GetFieldID(env,mClass,"native_para","I"); mMethodID=(*env)->GetMethodID(env,mClass,"SubJava","(II)I"); mMethodAddID=(*env)->GetMethodID(env,mClass,"AddJava","(II)I");}JNIEXPORT jint JNICALL Java_jnipack_JniClass_Add(JNIEnv *env, jobject thiz, jint a, jint b){ jint res=0; jint para=0; para=(jint)(*env)->GetIntField(env,mObject,mFieldID); res=(*env)->CallIntMethod(env,mObject,mMethodAddID,a,(b+para)); return res;}JNIEXPORT jstring JNICALL Java_jnipack_JniClass_getLibVersion(JNIEnv *env, jobject thiz){ return (*env)->NewStringUTF(env,"jnilibs : 1.0"); }
补充上面的内容,传递数组的方法j*array,*代表int等数据类型:
java代码增加:
public native int AddArray(int[] arr);
Jni实现代码中:
JNIEXPORT jint JNICALL Java_jnipack_JniClass_AddArray(JNIEnv *env, jobject thiz, jintArray arr) { jint len = 5; jint i = 0; jint res = 0; jint *arri; arri = (*env)->GetIntArrayElements(env, arr, 0); for (i = 0; i < 5; i++) { res = res + arri[i]; } return res;}
调用:
<4> : 现在在上面的工程中继续添加一个CPP的程序:
plus.h:
#ifndef PLUS_HEADER_H__#define PLUS_HEADER_H__class cale{public: cale(){};//不要添加virtual修饰符 virtual ~cale(){}; virtual int addplus(int a,int b); virtual char* showmsg();};#endif
plus.cpp:
#include "plus.h"char* cale::showmsg(){ return "cpp program !";};int cale::addplus(int a,int b){ return a+b;};
%module swig%{#include "plus.h"%}%include "plus.h"
swig.sh:
#!/bin/bashswig -c++ -java -package orgcpp -outdir ../src/orgcpp -o plusplus.cpp swig.i
LOCAL_PATH :=$(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE := jnilibsLOCAL_SRC_FILES := JniClass.c plusplus.cpp plus.cpp#LOCAL_CFLAGS :=-frttiinclude $(BUILD_SHARED_LIBRARY)
package com.org.androidjnicppdemo1;import orgcpp.cale;import jnipack.JniClass;import android.os.Bundle;import android.app.Activity;import android.view.Menu;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.Toast;public class MainActivity extends Activity implements OnClickListener{ private Button mGetVerBtn; private Button mCallNativeAddBtn; private Button mCppBtn; private JniClass jClass=new JniClass(); // private cale ce=new cale(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mGetVerBtn=(Button)findViewById(R.id.getver); mGetVerBtn.setOnClickListener(this); mCallNativeAddBtn=(Button)findViewById(R.id.callnativeadd); mCallNativeAddBtn.setOnClickListener(this); mCppBtn=(Button)findViewById(R.id.cpp); mCppBtn.setOnClickListener(this); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public void onClick(View arg0) { // TODO Auto-generated method stub int id; id=arg0.getId(); switch(id){ case R.id.getver: Toast.makeText(this, "lib : "+jClass.getLibVersion(), Toast.LENGTH_SHORT).show(); break; case R.id.callnativeadd: Toast.makeText(this, "native call : "+jClass.Add(16, 12), Toast.LENGTH_LONG).show(); break; case R.id.cpp:// Toast.makeText(this, "cpp : "+ce.showmsg(), Toast.LENGTH_LONG).show(); break; } }}
综合上面:
<1> : jni回调java代码;
<2> : java调用jni的c代码;
<3> : java调用jni的c++代码;
<4> : 增加常量native_para传递和使用;
其他图片:
下一节开始jni多线程操作.