このサンプルプログラムは、Cで記述されたnative
メソッドを呼び出すためのものです。
Javaコード
class HelloWorld {
private native void print();
public static void main( String args[] ) {
new HelloWorld().print();
}
static {
System.loadLibrary("HelloWorld");
}
}
これを書いた後、プログラムをコンパイルし、JNI
スタイルのヘッダーファイルを生成しました。
生成されるヘッダーファイルは:です
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <C:\Program Files\Java\jdk1.7.0\include\jni.h>
/* Header for class HelloWorld */
#ifndef _Included_HelloWorld
#define _Included_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: HelloWorld
* Method: print
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_HelloWorld_print
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
およびcで記述されたネイティブメソッド
#include <C:\Program Files\Java\jdk1.7.0\include\jni.h>
#include <C:\Program Files\Java\jdk1.7.0\include\win32\jni_md.h>
#include <stdio.h>
#include "HelloWorld.h"
JNIEXPORT void JNICALL Java_HelloWorld_print( JNIENv *env , jobject obj) {
printf("Hello World!\n");
return;
}
コンパイル時に表示されるエラーはfatal error C1083: Cannot open include file: 'jni_md.h': No such file or directory
また、私のコンパイラはjobject obj
と言うthis class does not have storage class or specifier
。下線*env
expected a ')'
。
なぜこのエラーが発生するのですか?
jni.h
は#include <jni_md.h>
は、インクルードパスにその場所を追加していないために失敗します。
これらのエントリの両方をCコンパイラのインクルードパスに追加してみてください。
C:\Program Files\Java\jdk1.7.0\include
C:\Program Files\Java\jdk1.7.0\include\win32
win32
パスは、jni.h
がセットアップされます。
最初にネイティブコードに次のヘッダーファイルを含める必要があります
#include <jni.h>
私の場合、UNIXシステムでは、
このヘッダーファイルjni.h
は/usr/lib/jvm/Java-8-openjdk-AMD64/include/
にあります
また、jni_md.h
は/usr/lib/jvm/Java-8-openjdk-AMD64/include/linux
にあります
システム内のJavaインストールパスがリダイレクトする場所を知っている場合、上記のファイルへのパスを取得できます。次の一連のコマンドで実行できます。
whereis Java
/usr/bin/Java /usr/share/Java /usr/share/man/man1/Java.1.gz
ls -l /usr/bin/Java
/usr/bin/Java -> /etc/alternatives/Java
ls -l /etc/alternatives/Java
/etc/alternatives/Java -> /usr/lib/jvm/Java-8-openjdk-AMD64/jre/bin/Java
(->)はシンボリックリンクです。
/usr/lib/jvm/Java-8-openjdk-AMD64/jre/bin/Java
です。また、ネイティブコンパイルの実行中に
jni.h
&jni_md.h
ファイルパスを含めることを忘れないでください。
コンパイル:-
gcc -I /usr/lib/jvm/Java-8-openjdk-AMD64/include/ -I /usr/lib/jvm/Java-8-openjdk-AMD64/include/linux/ -o libHelloWorld.so -shared *nativeSourceCodeFile*.c
(-I)はパスを識別します。
jni.h
]のパスが参照として提供されます。jni.h
は、jni_md.h
の明示的なインポートを行います。 #include "jni_md.h"
&そのため、コンパイル時にjni_md.h
ファイルへの次の参照を提供しました。jni_md.h
には、jbyte、jint、jlongのマシン依存のtypedefが含まれています。実行:-
Java -Djava.library.path=. HelloWorld
次、
JNIEXPORT void JNICALL Java_HelloWorld_print( JNIEnv* env , jobject obj){
printf("Hello World!\n");
}
行われた小さな変更を確認し、実装してみてください。
一度この問題がありました。私の解決策は、実際にはjni.hの内部#includeを"jni_md.h"
から"win32/jni_md.h"
に編集することでした。
これを試して、
HelloWorld.c
#include "HelloWorld.h"
#include <stdio.h>
JNIEXPORT void JNICALL Java_HelloWorld_print(JNIEnv *env, jobject obj)
{
printf("Hello World!\n");
return;
}
Cl.exeを使用してコンパイルします(VC++を使用しており、CL.EXEはコマンドラインスイッチに従って必要です)。
c:\> cl -c/I "c:\ Program Files\Java\jdk1.7.0\include"/I "c:\ Prog ram Files\Java\jdk1.7.0\include\win32" HelloWorld.c
.objモジュールのリンク
c:\> link/libpath = "c:\ Program Files\Java\jdk1.7.0\lib" HelloWorld.obj/dll