【Java】【C】【C++】 JNI ~ Java から C++ のソースを呼び出す ~

■ はじめに

 * Java から C++ のソースを呼び出すために、JNI(Java Native Interface)を使う

補足:JNA (Java Native Access)

 * Java から C++ のソースを呼び出すだけであれば、以下の関連記事のJNAの方がよさそう。
https://blogs.yahoo.co.jp/dk521123/36187289.html

■ 作成環境例

 * WindowsXP
 * Eclipse
 * Visual Studio C++ 2008 Express

■ 作成手順

1) Java側について(その1)

 1) Eclipseを立ち上げ、DLLの関数を呼び出すメソッドをnative宣言するクラスを作成
 (サンプルの「JniSample.java」を参考に)

 2) DLLをロードするクラスを作成
 (サンプルの「Main.java」を参考に)

 3) C++のヘッダファイルを作成するために...
    プロジェクトに、build.xml を追加し、サンプルの「build.xml」を参考に修正する

 4) Eclipseのメニューにおいて、[Window]-[Show View]-[Ant]を選択

 5) Antタブで、アリアイコン(Add Buildfiles)を押下し、手順1-3)で作成した「build.xml」を追加する

 6) Antタブで、「create c header」を選択し、三角(緑)アイコン(Run)を押下
 ⇒ F5(リフレッシュ)すれば、「com_jni_JniSample.h」ができているはず

2) C++側について(その1)

 1) VisualStudioを立ち上げ、[ファイル]-[新規作成]-[プロジェクト]-[Win32]-[Win32プロジェクト]を選択し
    ソリューション名(例「SampleJni」)を入力し、「OK」押下

 2) 「次へ」押下し、「アプリケーションの種類」を「DLL」を選択し、「完了」押下

 3) ソリューションエクスプローラのフォルダ「ヘッダーファイル」を右クリックし
    [追加]-[既存の項目]を選択し、手順1-6)で作成したヘッダーファイル「com_jni_JniSample.h」を選択

 4) C++のソースを追加し、C++側のソースを実装
 (サンプルの「JniSample.cpp」を参考に)

 5) VisualStudioのメニューで、[ツール]-[オプション]-[プロジェクトおよびソリューション]-[VC++ディレクトリ」
    を選択し、「ディレクトリを表示するプロジェクト」欄で[インクルードファイル]を選択し、
  フォルダアイコン押下し、以下のフォルダを追加し、「OK」押下

 * C:\Program Files\Java\jdkX.X.X_XX\include (例「C:\Program Files\Java\jdk1.7.0_25\include」)
  ⇒ 「jni.h」のありかを示すため
 * C:\Program Files\Java\jdkX.X.X_XX\include\win32 (例「C:\Program Files\Java\jdk1.7.0_25\include\win32」)
  ⇒ 「jni_md.h」のありかを示すため

 7) ビルドする(「SampleJni.dll」が作成される)

3) Java側について(その2)

 1) Eclipseにおいて、該当のプロジェクトを選択した状態で、[File]-[Import]-[General]-[File System]
  を選択し、「Next」押下
 2) 手順2-7で作成したDLL(この例の場合「SampleJni.dll」)を選択し、「Finish」押下
 3) 手順1-1) で作成したソース(この例の場合「JniSample.java」)を実行
 ⇒ 下記の「出力結果(From Eclipse)」のようになれば成功。

■ サンプル

Java

Main.java
package com.jni;

public class Main {
   public static void main(String[] args) {
      JniSample jni = new JniSample();
      System.out.println("Result : " + jni.getHellow("Mike"));
   }
}
JniSample.java
package com.jni;

public class JniSample {
   static {
      System.loadLibrary("SampleJni");
   }
   
   public native String getHellow(String name);
}
build.xml
<project basedir="./"> 
  <property name="cpdir" value="${basedir}\bin"/> 
  <target name="create c header"> 
    <exec executable="javah"> 
      <arg value="-classpath"/> 
      <arg value="${cpdir}"/> 
      <arg value="-jni"/> 
      <arg value="com.jni.JniSample"/> <!-- ここを変える -->
    </exec> 
  </target> 
</project>

C++

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

#ifndef _Included_com_jni_JniSample
#define _Included_com_jni_JniSample
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_jni_JniSample
 * Method:    getHellow
 * Signature: (Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_jni_JniSample_getHellow
  (JNIEnv *, jobject, jstring);

#ifdef __cplusplus
}
#endif
#endif
JniSample.cpp
#include "stdafx.h"
#include "com_jni_JniSample.h"

JNIEXPORT jstring JNICALL Java_com_jni_JniSample_getHellow
(JNIEnv *env, jobject thisObj, jstring name){
	
	const char *inputData = env->GetStringUTFChars(name, 0);
	
	char result[256];
	strcpy_s(result, "Hellow World, ");
	strcat_s(result, inputData);
	strcat_s(result, " from Managed C++!!");
	
	env->ReleaseStringUTFChars(name, inputData);
	
	return env->NewStringUTF(result);
}

出力結果(From Eclipse

Result : Hellow World, Mike from Managed C++!!


関連記事

JNI ~ C++ から Java のソースを呼び出す ~

https://blogs.yahoo.co.jp/dk521123/33067170.html

JNIで、エラー「java.lang.UnsatisfiedLinkError」が表示され、プログラムが動かない

https://blogs.yahoo.co.jp/dk521123/33196046.html

JNA (Java Native Access)

https://blogs.yahoo.co.jp/dk521123/36187289.html