最近在做OpenCV4Android开发的时候,需要从摄像头捕获多个图片,传值给本地对象,每次捕获到图片都更新数据,最后将计算得到的数据传给JAVA层,并在界面中显示。经过摸索和调试后,找到了通过本地对象的地址,来实现JAVA和本地类交互的方法。
下面,通过一个小例子进行示例说明,本例子完成通过点击按钮控件,实现本地对象的成员数据自加,并显示的功能:
首先这是我们C++类的代码,能实现自加很简单的类,能完成测试就好:
class TestNDK{private: int num;public: TestNDK():num(0){ } void numAddSelf(){ num++; } int getNum(){ return num; }};
然后再写一个JAVA类,通过这个类,加载动态链接库和本地函数,还有与本地方法交互的方法,更利于管理:
package com.pplxlee.testndk;public class TestNDKClass { // 加载动态链接库 static { System.loadLibrary("TestNDK"); } // 本地对象的地址,以long的形式保存 private long mAddr; // 构造函数调用本地类的创建函数 TestNDKClass(){ mAddr = nativeCreateObj(); } public void release(){ nativeRelease(mAddr); } public int getNum(){ return nativeGetNum(mAddr); } public void numAddSelf(){ nativeNumAddSelf(mAddr); } private static native long nativeCreateObj(); private static native void nativeRelease(long objAddr); private static native int nativeGetNum(long objAddr); private static native void nativeNumAddSelf(long objAddr); }
下面是实现jni本地方法的代码:
#includeextern "C"{// 构造本地对象,一定要用new关键字构造,否则,方法结束后,对象会被垃圾回收,之后通过地址访问,只会得到随机的“垃圾”JNIEXPORT jlong JNICALL Java_com_pplxlee_testndk_TestNDKClass_nativeCreateObj( JNIEnv *, jclass){ TestNDK* ndkObjectAddr = new TestNDK(); return ((long)ndkObjectAddr);}// 有new就必须有delete,最后不要忘记在本地对象不再需要时,释放其内存JNIEXPORT void JNICALL Java_com_pplxlee_testndk_TestNDKClass_nativeRelease( JNIEnv *, jclass, long addrNdkObject){ TestNDK* ndkObjectAddr = (TestNDK*)addrNdkObject; delete ndkObjectAddr;}JNIEXPORT jint JNICALL Java_com_pplxlee_testndk_TestNDKClass_nativeGetNum( JNIEnv *, jclass, long addrNdkObject){ TestNDK* ndkObjectAddr = (TestNDK*)addrNdkObject; return (ndkObjectAddr->getNum());}JNIEXPORT void JNICALL Java_com_pplxlee_testndk_TestNDKClass_nativeNumAddSelf( JNIEnv *, jclass, long addrNdkObject){ TestNDK& ndkObject = *(TestNDK*)addrNdkObject; ndkObject.numAddSelf();}}
下面就是我们的MainActivity
public class MainActivity extends Activity { TestNDKClass mObj; TextView tv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mObj = new TestNDKClass(); tv = (TextView)findViewById(R.id.textView1); tv.setText(String.valueOf(mObj.getNum())); Button btn = (Button)findViewById(R.id.button1); btn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub mObj.numAddSelf(); tv.setText(String.valueOf(mObj.getNum())); } }); } @Override protected void onDestroy(){ super.onDestroy(); mObj.release(); } }
运行结果如下图所示,每次点击按钮,数字都会+1: