JavaとC++を連結して実行する

JNI(Java Native Interface)と呼ばれる仕組みを使います。
これにより、JavaからC++で書いたコードの関数呼び出し(またはその逆)が可能になります。

以下で、C++で書いたgetDataの関数を、Javaのコードから呼び出す例(Windows)を示します。
まず、JavaからC言語のgetDataを実行するためのJavaのクラスを作る必要があります。 そのクラス名をCLangCallクラスとして、以下に示します。またコンパイルしているコマンドも示します。

package clang;

//C言語のコードを読むためのコード
public class CLangCall
{
	//staticブロックで、最初に一度だけ確実に実行する仕組み(静的初期化子)
	static
	{
		System.loadLibrary("cpplib");//cpplibは、ライブラリの名前
	}

	// 以下が、 C言語の命令の宣言部分
	private native byte[] getgetData(byte []a);

	public static void main(String[] args)
	{

		String s = "TEST文字列";

		CLangCall me = new CLangCall();
		
		byte[] a = me.getgetData(s.getBytes());

		System.out.println(new String(a));
	}
}

Z:\java>javac clang\CLangCall.java

次に、 このクラスからC言語に必要なヘッダーファイルを生成します。 以下に実行例と生成されたヘッダーファイルを示します。


Z:\java>javah -d Z:\java\clang\cpplib\cpplib clang.CLangCall

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

#ifndef _Included_clang_CLangCall
#define _Included_clang_CLangCall
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     clang_CLangCall
 * Method:    getgetData
 * Signature: ([B)[B
 */
JNIEXPORT jbyteArray JNICALL Java_clang_CLangCall_getgetData
  (JNIEnv *, jobject, jbyteArray);

#ifdef __cplusplus
}
#endif
#endif

次に、cpplib.dllの名前の ライブラリを作成するプロジェクトを作成し、
Java_clang_CLangCall_getgetDataの関数を定義します。 以下にそのプログラム例を示します。

#include "clang_CLangCall.h"

JNIEXPORT jbyteArray JNICALL Java_clang_CLangCall_getgetData
  (JNIEnv *env, jobject j_obj, jbyteArray j_array)
{
	// バイト列生成
	jbyteArray arrj = env->NewByteArray(5);

	//// 要素列取得 arrjをコピーして、そのポインタを返す。@
	jbyte * elems = env->GetByteArrayElements(arrj, NULL );

	//// 要素列取得 j_arrayをコピーして、そのポインタを返す。A
	jbyte * elems2 = env->GetByteArrayElements(j_array, NULL );

	elems[0] = elems2[0] + ('a'-'A');
	elems[1] = elems2[1] + ('a'-'A');
	elems[2] = elems2[2] + ('a'-'A');
	elems[3] = elems2[3] + ('a'-'A');
	elems[4] = '-';

	//  arrjに、elemsから、コピーする。(先頭から5つの要素をarrjへコピー)
	env->SetByteArrayRegion(arrj, 0, 5, elems);

	env->ReleaseByteArrayElements(arrj, elems, 0);// @の取得を開放
	env->ReleaseByteArrayElements(j_array, elems2, 0);// Aの取得を開放

	return arrj;
}

最後で、 実行する前にライブラリが実行できるよう、 環境変数 path にライブラリの位置を追加設定し、 それから実行している例です。


Z:\java>set path=Z:\java\clang\cpplib\release;%path%

Z:\java>java clang.CLangCall
test-

Z:\java>