[ジャワ – ℃] C関数はJavaで呼び出す – JavaでC関数を呼び出す

あなたは、Javaプログラムライブラリを書きたかったが、いくつかの言語が好きでなかった (Cなど) 実行する? それはあなたがこの記事を読んで一つの理由である, またはいくつかの他の理由は、あなたがより速く実行できるJavaプログラムにCの関数を使用しますか!

これを行うには, あなたは、JNIライブラリを使用する必要があります (Javaネイティブ·インターフェース), それは、Javaおよびその逆からC関数を呼び出すことができます. 基本的には, 我々は、Cの関数を記述します, ライブラリに翻訳され、JNIを通してJavaライブラリから関数を呼び出す. 我々は、それが徐々に階乗と呼ばれる関数の例を通して学ぶ回します. 私は、すべてのデスクトップと同じフォルダに以下のファイルを書いたメモ.

実施のプロセスで, Ubuntuの上で彼の作品, 多少変化することができるWindowsまたはLinuxディストリビューション上で. 私が相談した後に書いたこの記事は、 2 投稿 JavaからC関数の呼び出しJavaからC関数を呼び出す, しかし、実装プロセスは、いくつかのエラーが発生したため、その解決策も含まれています.

目次
ステップ 1: Javaクラスファイルにファイルを作成し、コン​​パイルする
ステップ 2: javahが持つヘッダファイルを作成します。
ステップ 3: 共有するCライブラリのコンパイル
ステップ 4: Javaの実行
いくつかのバグを修正

ステップ 1: Javaクラスファイルにファイルを作成し、コン​​パイルする


この段階では、我々はCから書き込まれているライブラリや関数の宣言をロードする必要が.

class CallCFunction {
	
	// report funcion write in C.
	private native long factorial(int n);
	public static void main(String[] args) {
		CallCFunction ccf = new CallCFunction();
		int n = 5;
		System.out.println(n + "! = " + ccf.factorial(5));
	}
	
	// load library factorial to use.
	static {
		System.loadLibrary("factorial");
	}
}

それを翻訳するために、ファイルを作成した後:

javac CallCFunction.java

ステップ 2: javahが持つヘッダファイルを作成します。

宣言されたJavaファイルで記述された階乗関数のCプログラム, そこで、使用するヘッダファイルを作成する必要があります.

javah -jni CallCFunction

上記のコマンドを実行した後, ファイル CallCFunction.h 作成されます. あなたが行に注意を払う 15,16, ここでは、Cプログラムで書くつもり関数である.

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class CallCFunction */

#ifndef _Included_CallCFunction
#define _Included_CallCFunction
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     CallCFunction
 * Method:    factorial
 * Signature: (I)J
 */
JNIEXPORT jlong JNICALL Java_CallCFunction_factorial
  (JNIEnv *, jobject, jint);

#ifdef __cplusplus
}
#endif
#endif

ステップ 3: 共有するCライブラリのコンパイル


ファイルを作成します。 factorial.c 計算された階乗を含む. あなたは、コピー 2 現在 15, 16 CallCFunction.hファイルと、私たちのより多くのは、以下のプログラムに回っている記入.

#include <jni.h>  
#include <stdio.h>  
#include "CallCFunction.h"   
JNIEXPORT jlong JNICALL Java_CallCFunction_factorial (JNIEnv *env, jobject obj, jint n)
{
	printf("funcion 'factorial' create in C programn");
	int i;
	long result = 1;
	for (i = 2; i <= n; i++)
	{
		result *= i;
	}

	return result;
}

その中で, 二行目 4 階乗を計算する関数である, とき、jlong 長いとしてのみ戻り値, 2 パラメータ のJNIEnv * ENVするjobject OBJ デフォルトであり、あなたが注意を必要としない (そのまた、それを認識していない), パラメーター 3 た JINT N 変数を参照する int型のn 機能に対応する 階乗(int型のn) ファイルCallCFunction.javaで.

今、私たちは、ライブラリを作成し、Javaを含むフォルダにそれを共有する (あなたのJavaを含むフォルダは、オフラインで異なる場合があります). CallCFunction.javaでは、ファイルライブラリをロード 階乗 コマンド System.loadLibraryを(“階乗”);, ライブラリので、我々は複数の文字列を持っている LIB 前すなわち libfactorial.so

gcc -shared -I/usr/lib/jvm/jdk1.8.0_05/include/ factorial.c -o libfactorial.so

ステップ 4: Javaの実行


今、私たちは、プログラムを実行することで恩恵を受けているだけ.

java -Djava.library.path=. CallCFunction

ザ· -Djava.library.path =. あなただけの現在のディレクトリに作成したライブラリを見つけることができますプログラムを教えている (ファイルフォルダlibfactorial.so). また、あなたはコマンドを使用してディレクトリに環境変数を設定することができます 輸出LD_LIBRARY_PATH =. (最後のドットと), あなたはコマンドで右実行することができます javaのCallCFunction

JavaでCを呼び出します

いくつかのバグを修正


実施のプロセスで, 私はいくつかのエラーを満たしている, あなたは私のような場合には、以下の救済に従うことを試みる, あなたはこの同じ取引所で共有することができ、他の場合にエラー.

1. javaコマンドバンドを変換することができません
JDKをインストールするにもかかわらず、Javaのjavacコマンドを変換できない場合、おそらくあなたはそれのために環境変数を設定していない. あなたは、Javaファイルを見つける, javacは, javahは任意のディレクトリに位置し、ディレクトリに環境変数を進める. にJDKを仮定 “/USR / libに/ jvmの/ jdk1.8.0_05 /”

export JAVA_HOME=/usr/lib/jvm/jdk1.8.0_05/
export PATH=$JAVA_HOME/bin:$PATH

2. ライブラリjni.h中が見つかりません
エラーがこのライブラリを見つけられませんでしたサービスは、それが使用する環境変数を設定していない方は. あなたがこれを行う必要があります. 例えば、彼の:

export LD_LIBRARY_PATH=/usr/lib/jvm/jdk1.8.0_05/include/

3. エラーファイルヘッダを作成する
ヘッダファイルを作成するプロセスで (CallCFunction.h), 次のエラーが発生することがあります:

Exception in thread "main" java.lang.IllegalArgumentException: Not a valid class name: HelloWorld
	at com.sun.tools.javac.api.JavacTool.getTask(JavacTool.java:129)
	at com.sun.tools.javac.api.JavacTool.getTask(JavacTool.java:107)
	at com.sun.tools.javac.api.JavacTool.getTask(JavacTool.java:64)
	at com.sun.tools.javah.JavahTask.run(JavahTask.java:503)
	at com.sun.tools.javah.JavahTask.run(JavahTask.java:329)
	at com.sun.tools.javah.Main.main(Main.java:46)

あなたは* .classファイルが含まれていない別のフォルダでコマンドを実行すると、それはだ生成された翻訳* .javaファイル. 言い換えれば、ファイル* .classファイルを見つけることができません. あなたが配置する必要があります クラスパス クラスファイルを含むフォルダへ. それはであると仮定すると デスクトップ.

javah -jni -classpath /home/nguyenvanquan7826/Desktop/ HelloWorld

4. ライブラリjni_md.hが見つかりません
あなたが見つける場所このライブラリコンピュータ. 彼の, これは次の場所にあります。 /USR / libに/ jvmの/ jdk1.8.0_05 /含める/ Linuxの, 今だけにコピー /USR / libに/ JVMは/ jdk1.8.0_05 / /含める (ファイルforder jni.h中が含まれています).