android ndk初歩1
ndk , ndk 。 , ,ndk jni ,ndk , , 。ndk r7 cyg , qq, , linux , Windows qq, 。
ndk 。 。 ,ndk-build linux cygwin, ndk prebuild 。awk
, , sample , 。 。
1
package com.example.hellojni;
import android.app.Activity;
import android.os.Bundle;
import android.widget.Toast;
public class HelloJni extends Activity {
/**
* @author ThinkinBunny Called when the activity is first created.
*/
public native String stringFromJNI();
public native int resultRet(int x, int y);// , ,c ,
/*
* This is another native method declaration that is *not* implemented by
* 'hello-jni'. This is simply to show that you can declare as many native
* methods in your Java code as you want, their implementation is searched
* in the currently loaded native libraries only the first time you call
* them.
*
* Trying to call this function will result in a
* java.lang.UnsatisfiedLinkError exception !
*/
public native String unimplementedStringFromJNI();
/*
* this is used to load the 'hello-jni' library on application startup. The
* library has already been unpacked into
* /data/data/com.example.HelloJni/lib/libhello-jni.so at installation time
* by the package manager.
*/
static {
System.loadLibrary("hello-jni");
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
System.out.println(resultRet(3, 4));
Toast.makeText(getApplicationContext(),
stringFromJNI() + "|" + resultRet(3, 4), 1).show();
}
}
このコードは簡単で、注釈もはっきりしています.ここでは2つだけ説明します.
static{ System.loadLibrary("hello-jni"); }
プログラムが実行を開始するとhello-jniがロードされることを示し、static領域で宣言されたコードはonCreateメソッドより先に実行されます.プログラムに複数のクラスがあり、HelloJniというクラスがアプリケーションのエントリではない場合、hello-jni(完全な名前はlibhello-jni.so)というライブラリは、HelloJniというクラスを初めて使用するときにロードされます.
public native String stringFromJNI(); public native String unimplementedStringFromJNI();
この2つのメソッドの宣言にはnativeキーワードが含まれていることがわかります.このキーワードは、この2つのメソッドがローカルメソッドであることを示しています.つまり、この2つのメソッドはローカルコード(C/C++)によって実現され、javaコードでは宣言にすぎません.
このプロジェクトをeclipseでコンパイルし、対応するものを生成する.classファイルは、生成のため、次のステップまでに完了する必要があります.hファイルは対応するものが必要である.classファイル.
そしてcdはこのプロジェクトのsrcの下に
PS E:\workspace\HelloJni\src> javah -jni com.example.hellojni.HelloJni
ネット上でjavah-classpath bin-d jni comと言います.example.hellojni.ハローJni、しかし私のはずっと間違いです:'comが見つかりません.example.hellojni.HelloJni'のクラスファイル.
多くの人がbinの下で、私はずっと失敗していると言っていますが、何が原因なのか分かりません.出勤して同僚に聞いてみました.
続きます.はい、プロジェクトディレクトリnewにjniフォルダがあります.ディレクトリ構造は、AndroidManifestです.xml assets bin default.properties gen res srcよし、
javah -jni com.example.hellojni.HelloJni
実行完了あなたのディレクトリをリフレッシュし、com_example_hellojni_HelloJni.h jniに引きずり込んで、このファイルは何の役にも立たないようですcom_を見てみましょうexample_hellojni_HelloJni.hの内容:
com_example_hellojni_HelloJni.h :
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_hellojni_HelloJni */
#ifndef _Included_com_example_hellojni_HelloJni
#define _Included_com_example_hellojni_HelloJni
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_example_hellojni_HelloJni
* Method: stringFromJNI
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_example_hellojni_HelloJni_stringFromJNI
(JNIEnv *, jobject);
/*
* Class: com_example_hellojni_HelloJni
* Method: resultRet
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_example_hellojni_HelloJni_resultRet
(JNIEnv *, jobject, jint, jint);
/*
* Class: com_example_hellojni_HelloJni
* Method: unimplementedStringFromJNI
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_example_hellojni_HelloJni_unimplementedStringFromJNI
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
上のコードのJNIEXPORTとJNICALLはjniのマクロで、androidのjniには必要ありません.もちろん書いても間違いありません.
上のソースコードからこの関数名はかなり長いことがわかりますね...でもやはりとても規則的で、完全に:java_に従いますpacakege_class_mathod形式で名前を付けます.
つまり、
Hello.JAvaにおけるstringFromJNI()メソッドはC/C++におけるJava_に対応するcom_example_hellojni_HelloJni_stringFromJNI()メソッド
HelloJni.JAvaのunimplementedStringFromJNI()メソッドは、C/C++のJava_に対応します.com_example_hellojni_HelloJni_unimplementedStringFromJNI()メソッド
注記:
Signature: ()Ljava/lang/String;
()Ljava/lang/String;
()関数を表すパラメータが空です(ここでは空とはJNIEnv*,jobjectの2つのパラメータ以外にパラメータがありません.JNIEnv*,jobjectはすべてのjni関数に必要な2つのパラメータで、それぞれjni環境と対応するjavaクラス(またはオブジェクト)自体を表します).
Ljava/lang/String; 関数の戻り値がjavaのStringオブジェクトであることを示します.
2.2該当するものを作成する.cファイル:
hello-jni.c :
/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include <string.h>
#include <jni.h>
/* This is a trivial JNI example where we use a native method
* to return a new VM String. See the corresponding Java source
* file located at:
*
* apps/samples/hello-jni/project/src/com/example/HelloJni/HelloJni.java
*/
jstring
Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
jobject thiz )
{
return (*env)->NewStringUTF(env, "Hello from JNI !");
}
jint
Java_com_example_hellojni_HelloJni_resultRet
(JNIEnv * env, jobject thiz, jint a, jint b){
jint x=0;
x=a+b;
return x;
}
hello-jni.cファイルはすでに作成されています.com_example_hellojni_HelloJni.hファイルは削除して、もちろん残してもいいですが、私はやはり不要なファイルをきれいに片付けることに慣れています.
Android.mkファイル
jniディレクトリ(hello-jni.c同級ディレクトリ)にAndroid.mkファイルを新規作成します.Android.mkファイルはAndroidのmakefileファイルで、内容は以下の通りです.
# Copyright (C) 2009 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hello-jni
LOCAL_SRC_FILES := hello-jni.c
include $(BUILD_SHARED_LIBRARY)
このアンドロイドmkファイルは短いので、行ごとに説明します.
LOCAL_PATH := $(call my-dir)
Android.mkファイルはまずLOCAL_を定義する必要があります.PATH変数.開発ツリーでソースファイルを検索するために使用します.この例では、マクロ関数「my-dir」は、現在のパス(すなわちAndroid.mk fileファイルを含むディレクトリ)を返すためにコンパイルシステムによって提供される.
include $( CLEAR_VARS)
CLEAR_VARSはコンパイルシステムによって提供され、GNU MAKEFILEに多くのLOCALをクリアさせることを指定します.XXX変数(例えば、LOCAL_MODULE、LOCAL_SRC_FILES、LOCAL_STATIC_LIBRARIESなど)、LOCALを除くPATH .これは、すべてのコンパイル制御ファイルが同じGNU MAKE実行環境にあり、すべての変数がグローバルであるため必要です.
LOCAL_MODULE := hello-jni
コンパイルされたターゲットオブジェクト、LOCAL_MODULE変数は、Androidを識別するために定義する必要があります.mkファイルに記述されている各モジュール.名前は一意で、スペースは含まれません.
注意:コンパイルシステムは自動的に適切な接頭辞と接尾辞を生成し、言い換えれば、「hello-jni」と命名された共有ライブラリモジュールは、「libhello-jni」を生成する.so'ファイル.
重要な注意事項:
ライブラリを「libhello-jni」と命名すると、コンパイルシステムはlib接頭辞を追加せず、「libhello-jni」も生成します.so'は、AndroidプラットフォームからのソースコードのAndroidをサポートするためです.mkファイル、もしあなたが本当にそうする必要があるなら.
LOCAL_SRC_FILES := hello-jni.c
LOCAL_SRC_FILES変数には、モジュールにコンパイルするCまたはC++ソースファイルが含まれている必要があります.コンパイルシステムは自動的に依存型のファイルを見つけるので、ここにヘッダーファイルと含むファイルをリストする必要はありません.コンパイラに直接渡されるソースファイルだけをリストすればいいです.
なお、デフォルトのC++ソースファイルの拡張子は'.cpp’. LOCAL_を定義するだけで、異なる拡張子を指定することもできます.DEFAULT_CPP_EXTENSION変数は、「cxx」ではなく「.cxx」で始まる小さなドットを忘れないでください.
include $(BUILD_SHARED_LIBRARY)
BUILD_SHARED_LIBRARYはコンパイル生成共有ライブラリを表し、コンパイルシステムが提供する変数であり、GNU Makefileスクリプトを指し、前回「include$(CLEAR_VARS)」が呼び出されてからLOCAL_に定義されたXXX変数の中のすべての情報は、何をコンパイルするか、どのように正しく行うかを決定します.そしてBUILD_STATIC_LIBRARY変数は、生成静的ライブラリ:lib$(LOCAL_MODULE)を表す.a, BUILD_EXECECUTABLEは、実行可能ファイルを生成することを示す.
cd workspaceHelloJniを下にしてndk-build
PS E:\workspace\HelloJni> ndk-build "Compile thumb : hello-jni <= hello-jni.c SharedLibrary : libhello-jni.so Install : libhello-jni.so => libs/armeabi/libhello-jni.so
eclipseでHelloJniプロジェクトを再コンパイルしapkを生成
eclipseでHelloJniプロジェクトをリフレッシュし、apk,libhello-jniを再コンパイルします.so共有ライブラリはapkファイルに一緒にパッケージされます.
へへへ、jniはsunの上であって、次の研究の下で