soを生成する

13842 ワード

参照:http://bbs.pediy.com/showthread.php?t=141960
説明:最近忙しいので、古い種目が切り落とされ、新しい種目が審査されたばかりです.加えて、NDKの文章はネット上にたくさんあります.そのため、この文章はネットから転載された.原文リンク:『Android:NDKプログラミング入門ノート』
APK反解之三:NDKコンパイル.soダイナミックライブラリ
なぜNDKを使うのですか?この間、仕事中にandroidのアプリケーションでandroidのルートファイルシステムのファイルにアクセスする必要がありましたが、アプリケーションの権限制限でこれらのファイルにアクセスできません.どうすればいいですか?したがって、これはNDKプログラミングに使用され、C/C++コードでシステムファイルへのアクセスを実現し、androidのjavaコード呼び出しのためにローカルライブラリを生成することで、javaコードでC/C++で作成されたライブラリのインタフェースを呼び出すことでシステムファイルへのアクセスを実現することができます.Android NDKの入門学習過程を紹介します.入門の最善の方法はAndroidが持参した例を学ぶことです.ここではAndroidのNDKが持参したdemoプログラム:hello-jniを学ぶことでこの目的を達成します.一、開発環境の構築a.androidのNDK開発はlinuxの下で行う必要がある:C/C++で書かれたコード生成をarm上で実行できる必要があるからである.soファイルは、クロスコンパイル環境に使用する必要がありますが、クロスコンパイルはlinuxシステムで完了する必要があります.b.android-ndk開発パッケージをインストールします.この開発パッケージはgoogle android公式サイトでダウンロードできます.この開発パッケージのツールを通じてandroid jniのC/C++のコードをライブラリc.androidアプリケーション開発環境にコンパイルすることができます.eclipse、java、android sdk、adtなどが含まれています.どのようにandroid-ndkをダウンロードしてインストールします私のここはくどくどしないで、インストールが終わった後に、android-ndkの道路の力を環境変数PATHの中に加える必要があります:
コード:
sudo gedit /etc/environment


EnvironmentのPATH環境変数にandroid-ndkのインストール方法を追加し、この変更した環境変数をすぐに有効にします.
コード:
source  /etc/environment


上記の手順を経て、コマンドラインでノックします.
コード:
ndk-bulid


ndk-build not foundではなく、ndk環境のインストールに成功したことを示すエラーがポップアップされます.
コード:
Android NDK: Could not find application project directory !    

Android NDK: Please define the NDK_PROJECT_PATH variable to point to it.    

/home/braincol/workspace/android/android-ndk-r5/build/core/build-local.mk:85: *** Android NDK: Aborting    .  Stop.


二、コードの作成1.まずjavaコードを書いてAndroidアプリケーションエンジニアリングHelloJniを構築し、HelloJniを作成します.JAvaファイル:HelloJni.java :
コード:
/* 

 * 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. */

 

 package com.example.hellojni;

 import android.app.Activity;

 import android.widget.TextView;

 import android.os.Bundle;

 

 public class HelloJni extends Activity{    

        /** Called when the activity is first created. */    

        

        @Override    

        public void onCreate(Bundle savedInstanceState)    {        

               super.onCreate(savedInstanceState);        

               /* Create a TextView and set its content.         

                * the text is retrieved by calling a native         

                * function.         */        

                

               TextView  tv = new TextView(this);        

               tv.setText( stringFromJNI() );        

               setContentView(tv);    

        }    

        /* A native method that is implemented by the     

         * 'hello-jni' native library, which is packaged     

         * with this application.     */    

         

         public native String  stringFromJNI();    

         /* 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");    

         }

 }


このコードは簡単で、注釈もはっきりしています.ここでは、a:static{ System.loadLibrary(「hello-jni」);}プログラムが実行を開始するとhello-jniがロードされ、static領域で宣言されたコードはonCreateメソッドより先に実行されます.プログラムに複数のクラスがあり、HelloJniというクラスがアプリケーションのエントリではない場合、hello-jni(完全な名前はlibhello-jni.so)というライブラリは、HelloJniというクラスを初めて使用するときにロードされます.b: public native String stringFromJNI(); public native String unimplementedStringFromJNI();この2つのメソッドの宣言にはnativeキーワードが含まれていることがわかります.このキーワードは、この2つのメソッドがローカルメソッドであることを示しています.つまり、この2つのメソッドはローカルコード(C/C++)によって実現され、javaコードでは宣言にすぎません.このプロジェクトをeclipseでコンパイルし、対応するものを生成する.classファイルは、生成のため、次のステップまでに完了する必要があります.hファイルは対応するものが必要である.classファイル.2.対応するC/C++コードを作成して勉強し始めたばかりの頃、困ったことになる問題がありました.対応するC/C++コードはどのように作成し、関数名はどのように定義しますか.ここではjavahというツールを用いて対応するものを生成する方法について述べる.hファイル、そしてこれに基づいて.hファイルは、対応するC/C++コードを記述する.2.1対応を生成する.hファイル:私の環境では、まず端末の下で設立されたばかりのHelloJniプロジェクトのディレクトリに入ります.
コード:
braincol@ubuntu:~$ cd workspace/android/NDK/hello-jni/ 


lsプロジェクトファイルの表示
コード:
braincol@ubuntu:~/workspace/android/NDK/hello-jni$ ls 

AndroidManifest.xml  assets  bin  default.properties  gen  res  src 


現在、標準のandroidアプリケーションがいくつかしかないファイル(クリップ)が表示されます.まず、プロジェクトディレクトリの下にjniフォルダを作成します.
コード:
braincol@ubuntu:~/workspace/android/NDK/hello-jni$ mkdir jni 

braincol@ubuntu:~/workspace/android/NDK/hello-jni$ ls 

AndroidManifest.xml  assets  bin  default.properties  gen  jni  res  src 


以下、対応するものを生成することができる.hファイル:
コード:
braincol@ubuntu:~/workspace/android/NDK/hello-jni$ javah -classpath bin -d jni com.example.hellojni.HelloJni 


-classpath bin:クラスの力を表す-d jni:生成されたヘッダファイルに格納ディレクトリcomを表す.example.hellojni.HelloJniは完全なクラス名であり、bin/com/example/hellojni/ディレクトリの下でHelloJniを生成することに成功した.classの基礎の上にあります.jniディレクトリの下に複数のディレクトリが表示されます.hファイル:
コード:
braincol@ubuntu:~/workspace/android/NDK/hello-jni$ cd jni/ 

braincol@ubuntu:~/workspace/android/NDK/hello-jni/jni$ ls 

com_example_hellojni_HelloJni.h


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 __cplusplusextern "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:    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形式で名前を付けます.つまりハロー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 

 */

 

jstringJava_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env, jobject thiz ){    

    return (*env)->NewStringUTF(env, "Hello from JNI !");

}


ここではJavaを実現しただけですcom_example_hellojni_HelloJni_stringFromJNIメソッド、Java_com_example_hellojni_HelloJni_HelloJni.JAvaではstringFromJNI()メソッドのみが呼び出されているので、unimplementedStringFromJNI()メソッドは実装されていなくても大丈夫ですが、javaで定義されているローカルメソッドをすべて実装して、空の関数を書いても良いでしょう.ないよりはましだ.Java_com_example_hellojni_HelloJni_stringFromJNI()関数は単純に「Hello from JNI!」という内容を返しただけです.のjstringオブジェクト(javaのStringオブジェクトに対応します).hello-jni.cファイルはすでに作成されています.com_example_hellojni_HelloJni.hファイルは削除して、もちろん残してもいいですが、私はやはり不要なファイルをきれいに片付けることに慣れています.3.hello-jniをコンパイルする.c対応するライブラリ3.1作成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)


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.cLOCAL_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は、実行可能ファイルを生成することを示す.3.2生成.so共有ライブラリファイル
コード:
braincol@ubuntu:~/workspace/android/NDK/hello-jni/jni$ cd .. 

braincol@ubuntu:~/workspace/android/NDK/hello-jni$ ls 

AndroidManifest.xml  assets  bin  default.properties  gen  jni  libs  obj  res  src 

braincol@ubuntu:~/workspace/android/NDK/hello-jni$ ndk-build 

Gdbserver      : [arm-linux-androideabi-4.4.3] libs/armeabi/gdbserver 

Gdbsetup       : libs/armeabi/gdb.setup 

Install        : libhello-jni.so => libs/armeabi/libhello-jni.so 


libhello-jniが正しく生成されていることがわかります.so共有ライブラリです.libs/armeabi/ディレクトリの下に行ってみましょう.
コード:
braincol@ubuntu:~/workspace/android/NDK/hello-jni$ cd libs/ 

braincol@ubuntu:~/workspace/android/NDK/hello-jni/libs$ ls 

armeabi 

braincol@ubuntu:~/workspace/android/NDK/hello-jni/libs$ cd armeabi/ 

braincol@ubuntu:~/workspace/android/NDK/hello-jni/libs/armeabi$ ls 

gdbserver  gdb.setup  libhello-jni.so


4.eclipseでHelloJniプロジェクトを再コンパイルし、apkeclipseでHelloJniプロジェクトをリフレッシュし、生成apk,libhello-jniを再コンパイルする.so共有ライブラリはapkファイルに一緒にパッケージされます.シミュレータで実行結果を確認:http://images.cnblogs.com/cnblogs_com/hibraincol/201105/201105302329223390.png