建立JNI层的本地对象,并与JAVA层交互方法

  最近在做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本地方法的代码:

#include <jni.h>

extern "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:

每次点击按钮,中间的数据都会+1

原文地址:https://www.cnblogs.com/pplxlee/p/5721054.html