2012年7月7日土曜日

JNIと汎用テキストマッピング

Corresponding of Generic-Text Mappings for JNI programming


こんにちは。イチ、プログラマのyu1rowです。

Javaで業務アプリなんかを作っていると、どうしてもネイティブの機能を使う必要が出てくるケースがあります。
そんなときにJNIが役に立つんですが、Windowsネイティブでの実装をする場合は文字列の変換が必要になる場合があります。
※Unicode/マルチバイトコード両対応にする必要性とか、説明が長くなるんで詳しくはグーグルにお任せするとします。

汎用文字列を使用してUnicode/マルチバイトコード両対応にしようとして変換のコードを毎回書くのが面倒なので備忘録としてソースコードを作ってみた&公開して凹ってもらおうってのが今回の趣旨です。

Source code


公開するコードは以下の2つです。両方使います。
ヘッダファイル(jniutil.h)
C++ソースコード(jniutil.cpp)

注意事項


  • プリコンパイル済みヘッダーを使用する場合、jniutil.cppでstdafx.hをインクルードするか、またはjniutil.hからはプロトタイプ宣言だけ残してinclude/define/typedefの記述をstdafx.hに移動してしまってください。
  • jniutil.hではjni.hをインクルードしていますが、VisualStudioの設定などで、Javaのインストール先にあるインクルードファイルのフォルダパスを参照するようにしておいてください。
    よくわからないという方は、詳しいWEBページが沢山あるので続きはその他WEBで。
  • STLを使用していますので、STLがNGな現場では当然NGとなりますのでご注意ください。
    MFC使いたいよーって人は...読み替えて勝手に改造しちゃってください。

使用方法


[tcout] Hello Worldとか
#include "jniutil.h"

void _tmain()
{
    tcout << _T("Hello World.") << std::endl;
}
ミソは"tcout"("tcin"ってのもtypedefしてある)。
jniutil.hのdefineを読めば何しているかわかると思います。

[tstring] findとか
#include "jniutil.h"

void _tmain()
{
    std::setlocale(LC_ALL, "");

    tstring text = _T("我輩は猫である");
    tcout << _T("\"") << text << _T("\"");
    if (text.find(_T("猫")) != tstring::npos)
    {
        tcout << _T("には猫が出てくる") << std::endl;
    }
    else
    {
        tcout << _T("には猫が出てこない") << std::endl;
    }
}
setlocaleしとかないとコンソールに正しく日本語が出力されない...場合があります。
std::basic_stringのテンプレート引数に_TCHARを与えて一般化したものをtypedefしてtstringとしています。
それだけなんですけど、とっても便利だと思いますし、JNIとか関係なく使えるんで他で使っても損は無いと思います。

実はここまではJNIとは関係ありません。関係あるのは以下の例です。

[JstringToTstring, TstringToJstring] : C++のコード例
#include "com_yu1row_blog_JniSample.h"
#include "jniutil.h"

JNIEXPORT jstring JNICALL Java_com_yu1row_blog_JniSample_ExecSample
(JNIEnv *env, jobject obj, jstring str)
{
    tstring tstr = JstringToTstring(env, str);
    tstr += tstr;
    return TstringToJstring(env, tstr);
}
JstringToTstringでJavaから渡されたjstringをtstringに、TstringToJstringで逆にtstringからjstringに変換できます。
[JNI] : 上記を使用するJavaの実装例
package com.yu1row.blog;

public class JniSample {
    static {
        System.loadLibrary("JniSample");
    }
    public native String ExecSample(String str);

    public static void main(String[] args) {
        JniSample sample = new JniSample();
        System.out.println(sample.ExecSample("あいうえお"));
    }
}

注意とお願い


今回公開したコードはバグがあるかもしれません。
バグのせいで何か迷惑を被ったと言われても責任は取れませんが、当エントリにて指摘いただければ(気が向けば)修正しますので気付いた点などあればどんどん凹って下さい。

0 件のコメント:

コメントを投稿