Java呼び出しC言語JNIライブラリ(Hello Worldインスタンス)
5554 ワード
Javaでc言語のライブラリを呼び出すには、ずっと不思議に思っていましたが、JavaがJNIというものを提供してくれたことも可能になりました.私たちとして、最も簡単なHello Worldから始めましょう.
まず、私たちがしたいことを話します.c言語でvoid sayHello()関数を定義します(Hello Worldを印刷します).そしてJavaでこの関数を呼び出してHello Wordを表示します.
JavaとC言語の2つの部分から説明します.
1. Java ぶぶん
まず、sayHello関数を明示するHelloNativeを定義します.関数はNativeタイプであることを明示します.以下のようにします.
このクラスをコンパイルしてclassファイルを生成します.
Javahによる必要なhファイルの生成
生成されたhファイルは、次のようになります.
上の自動生成プログラムを見てもいいです.プログラムincludeはjni.hです.このヘッダファイルは$JAVA_です.HOMEの下のincludeフォルダの下で.また生成した関数名が我々の関数名の前にJavaを付けたことを発見することができる.HelloNative.
2.C言語部分
上で生成したhファイルに基づいて、HelloNative.cppを作成してHello Worldを表示する関数を実現するように、対応するコード実装を作成します.以下のようにします.
コードの作成が完了した後、gccでライブラリファイルにコンパイルし、コマンドは以下の通りです.
これにより、現在のディレクトリの下にlibHelloNative.soのライブラリファイルが生成されます.このとき、必要なライブラリは生成され、C言語での作業は完了しました.
次に、Javaでプログラムを作成してテストする必要があります.プログラムの前に、ライブラリをロードする必要があります.ロード方法はJavaを呼び出すことです. System.loadLibrary("HelloNative");
しかし、コンパイル後、実行中に問題が発生しました.
ライブラリの読み込みに失敗しましたが、私たちのライブラリは現在のフォルダの下にあるのに、どうして読み込みに失敗しましたか?
System.getProperty(「java.library.path」)で見ると、java.library.pathには現在のディレクトリが存在しないことがわかります.主に以下の解決策があります.
1)生成されたライブラリをjava.library.pathのあるパスにコピーするのは、もちろんよくありません.
2)環境変数export LD_の設定LIBRARY_PATH=.:$LD_LIBRARY_PATH、現在のディレクトリをLD_に追加LIBRARY_PATH中
3)javaのオプションを設定し、現在のディレクトリを追加します.java-Djava.library.path=.$LD_LIBRARY_PATH
これで私たちのプログラムは成功して実行できます.表示されている「Hello World!」が見えます.
まず、私たちがしたいことを話します.c言語でvoid sayHello()関数を定義します(Hello Worldを印刷します).そしてJavaでこの関数を呼び出してHello Wordを表示します.
JavaとC言語の2つの部分から説明します.
1. Java ぶぶん
まず、sayHello関数を明示するHelloNativeを定義します.関数はNativeタイプであることを明示します.以下のようにします.
public class HelloNative {
public native void sayHello();
}
このクラスをコンパイルしてclassファイルを生成します.
javac HelloWorld.java
Javahによる必要なhファイルの生成
javah HelloNative
生成されたhファイルは、次のようになります.
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HelloNative */
#ifndef _Included_HelloNative
#define _Included_HelloNative
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: HelloNative
* Method: sayHello
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_HelloNative_sayHello
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
上の自動生成プログラムを見てもいいです.プログラムincludeはjni.hです.このヘッダファイルは$JAVA_です.HOMEの下のincludeフォルダの下で.また生成した関数名が我々の関数名の前にJavaを付けたことを発見することができる.HelloNative.
2.C言語部分
上で生成したhファイルに基づいて、HelloNative.cppを作成してHello Worldを表示する関数を実現するように、対応するコード実装を作成します.以下のようにします.
#include <stdio.h>
#include "HelloNative.h"
JNIEXPORT void JNICALL Java_HelloNative_sayHello(JNIEnv *, jobject)
{
printf("Hello World!
");
}
コードの作成が完了した後、gccでライブラリファイルにコンパイルし、コマンドは以下の通りです.
gcc -fPIC -I/usr/lib/jvm/java-7-openjdk-i386/include -I/usr/lib/jvm/java-7-openjdk-i386/include/linux -shared -o libHelloNative.so HelloNative.cpp
これにより、現在のディレクトリの下にlibHelloNative.soのライブラリファイルが生成されます.このとき、必要なライブラリは生成され、C言語での作業は完了しました.
次に、Javaでプログラムを作成してテストする必要があります.プログラムの前に、ライブラリをロードする必要があります.ロード方法はJavaを呼び出すことです. System.loadLibrary("HelloNative");
public class TestNative
{
static {
try {
System.loadLibrary("HelloNative");
}
catch(UnsatisfiedLinkError e) {
System.out.println( "Cannot load hello library:
" + e.toString() );
}
}
public static void main(String[] args) {
HelloNative test = new HelloNative();
test.sayHello();
}
}
しかし、コンパイル後、実行中に問題が発生しました.
Cannot load hello library:
java.lang.UnsatisfiedLinkError: no HelloNative in java.library.path
Exception in thread "main" java.lang.UnsatisfiedLinkError: HelloNative.sayHello()V
at HelloNative.sayHello(Native Method)
at TestNative.main(TestNative.java:13)
ライブラリの読み込みに失敗しましたが、私たちのライブラリは現在のフォルダの下にあるのに、どうして読み込みに失敗しましたか?
System.getProperty(「java.library.path」)で見ると、java.library.pathには現在のディレクトリが存在しないことがわかります.主に以下の解決策があります.
1)生成されたライブラリをjava.library.pathのあるパスにコピーするのは、もちろんよくありません.
2)環境変数export LD_の設定LIBRARY_PATH=.:$LD_LIBRARY_PATH、現在のディレクトリをLD_に追加LIBRARY_PATH中
3)javaのオプションを設定し、現在のディレクトリを追加します.java-Djava.library.path=.$LD_LIBRARY_PATH
これで私たちのプログラムは成功して実行できます.表示されている「Hello World!」が見えます.