Android:JNI呼び出しC++カスタムクラス

3988 ワード

一般的に、android studioを直接使用して生成されたコードも含めて、JNIでC++を呼び出す方法のコードです.しかし、新しい、またはC++のカスタムクラスを作成する必要がある場合があります.呼び出し時にC++を呼び出す方法のようにはできません.一部の他の人のブログを調べてみると、書いているのはあいまいで、この知識に触れたことがない人にとって友好的ではありません.いくつかの良いブログを参考にして、具体的な使い方を紹介します.
1.JNIプロジェクトを作成する便利さのために、システムにCMakeListsを自動的に生成させることができる.txtファイル、およびローカルライブラリをロードするコード.androidプロジェクトを作成するときは、ページの下にある「include C++support」オプションにチェックを入れ、デフォルトのオプションでnextをクリックします. 
今回C++クラスを使用する目的は、C++オブジェクトのいくつかの方法を使用することであり、簡略化のためにPersonオブジェクトを作成し、その設定を呼び出し、年齢を取得する方法です.
2.Javaクラスを作成し、JniPersonという名前のjavaクラスを新規作成し、必要な機能を記述します.このような機能をC++コードに関連付ける必要があります.オブジェクトのアドレスを渡すことで実現できます.つまり、JavaにC++オブジェクトを持つことができれば、まずそのオブジェクトのコンストラクション関数を呼び出し、メモリを開き、オブジェクトを生成し、そのオブジェクトの存在するアドレスをjavaオブジェクトに記録することで、次回はこのアドレスでC++のオブジェクトを見つけることができます.ここではlong型の数値をポインタとして使用します.次に、ローカルオブジェクトを作成し、アドレスを返します.コードは次のとおりです.
public class JniPerson {
    //  c++    
    long nativePerson;
    //    
    public JniPerson(){
        nativePerson = createNativeObject();
    }
    public void setAge(int age){
        setAge(nativePerson,age);
        return;
    }
    public int getAge(){
        return getAge(nativePerson);
    }
    /**    :  c++       */
    private native long createNativeObject();
    private native void setAge(long addr,int age);
    private native int getAge(long addr);
}

次のnativeメソッドは作成されたばかりの頃、赤で表示されていましたが、まず気にしないで、次のステップで解決します.上のpublicメソッドはjavaクラス自体のメソッドであり,その関数体は下で定義したnativeメソッドを呼び出す.
3.C++クラスを追加システムが自動的に生成するcppフォルダの下にあるnative-lib.cppファイルは、先に無視します.このcppフォルダに自分のC++クラスをインポートできます.もちろん自分で作成することもできます.ここでは、C++クラスを新規作成し、cppフォルダを右クリックしてnew->C++classを選択し、ポップアップダイアログボックスにカスタムC++クラスの名前を入力します.ここにPersonを記入し、OKをクリックすると、システムがPersonを作成します.cppファイルとPerson.hファイル、Personを修正します.hファイルは以下の内容である.
#ifndef CPPJNITEST_PERSON_H
#define CPPJNITEST_PERSON_H
 
class Person {
private:
    int age;
public:
    Person();
    int getAge();
    void setAge(int age);
};
 
#endif //CPPJNITEST_PERSON_H

次にPersonを修正します.cppは以下の内容である.
#include "Person.h"
#include 
 
extern "C"
JNIEXPORT jlong JNICALL
Java_com_example_lcq_cppjnitest_JniPerson_createNativeObject(JNIEnv *env, jobject obj) {
    jlong result;
    result =(jlong) new Person();
    return result;
}
 
extern "C"
JNIEXPORT void JNICALL
Java_com_example_lcq_cppjnitest_JniPerson_setAge(JNIEnv *env, jobject obj, jlong addr, jint age) {
    //        
    ((Person*)addr)->setAge(age);
}
 
extern "C"
JNIEXPORT jint JNICALL
Java_com_example_lcq_cppjnitest_JniPerson_getAge(JNIEnv *env, jobject obj, jlong addr) {
    return ((Person*)addr)->getAge();
}
 
 
int Person::getAge() {
    return this->age;
}
 
void Person::setAge(int age) {
    this->age = age;
}
 
Person::Person() {
 
}

私たちは一方でPersonを実現しましたhにおける方法は,一方,前のステップで実装のために赤く落札されたnativeコードを実現した.コード内の長い関数名には、以前に作成したJniPersonクラスでマウスを赤のJNIメソッドに配置した後、Alt+Enterを押すと、JNIメソッドの作成を促す簡単な生成方法があります.これにより、長い関数名の列を直接生成することができます.この列の関数名をコピーして使えばいいです(関数名の後に追加の文字を追加したり、追加の文字を削除したりすることがあります).
-createNativeObject関数を使用してオブジェクトを作成し、作成したオブジェクトのアドレスを返し、javaとの連絡を容易にします.
-setAge、getAgeメソッドでは、パラメータaddrはcreateNativeObjectが返すlongタイプのアドレスであり、javaでこのアドレスをC++に転送し、(Person*)addrを利用して、addrを当初作成したオブジェクトへのポインタに強制的に変換し、そのオブジェクトの「持参」メソッドを呼び出すことができます.
-次のいくつかの方法は、Personを実現することです.hで明記する方法.
4.CMakelistsを修正する.txtファイルシステムがこのファイルを作成してくれたので、add_に直接libraryでカスタマイズしたPersoncppを追加すればいい、元のnative-lib.cpp、削除できます.
5.関数呼び出しMainActivityではjavaオブジェクトJniPersonを作成し、そのメソッドを呼び出し、そのメソッドはC++クラスのメソッドを呼び出します.
   
@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        JniPerson mJniPerson = new JniPerson();
        mJniPerson.setAge(68);
        String mAge =  mJniPerson.getAge() + "";
 
        TextView tv = (TextView) findViewById(R.id.sample_text);
        tv.setText(mAge);
    }