2012年7月20日金曜日

こんなん作りたいシリーズ - Incrementalist

ゲーム:Incrementalist


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

↓こんなん作りたいってのをまずはjQueryとかで実装。たぶんスマホでも動きます。
[Incrementalist(仮)]
※ルール:全部のパネルを3にしたらクリア、それだけです

Androidで実装してみたいなぁ。
...今日はそれだけの記事です。

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("あいうえお"));
    }
}

注意とお願い


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

2012年7月6日金曜日

Windows 7 Home Premium と RDP

Windows 7 Home Premiumでリモートデスクトップしたいよう


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

メインの開発用に買ったZENBOOKですが、OSがWindows 7 Home Premium(x64)なので、リモートデスクトップ(ホスティング)が使えません。
あ、もちろんクライアントは使えますよ。
そんなとき、リモートデスクトップを使えるようにRDPのモジュールにパッチを当てる方法を見つけたのでご紹介です。
※勿論、これを実施するか否かは個人の判断の元、自己責任でお願いします

リモートデスクトップぅ?


そもそもリモートデスクトップは知ってますか?

要はWindowsをネットワーク経由で遠隔操作するサーバー/クライアント/プロトコルのことです。
クライアントは「Windowsキー」+「R」で出てくる「ファイル名を指定して実行」で「mstsc」と入力するとすぐ起動できます。れっつとらい。



あと、MicrosoftさんはMac用のクライアントも無料で公開してるんです。マカーな人は使ってみて下さいな。
Microsoft Remote Desktop Connection Client for Mac

他のイイコト


以下でパッチの紹介をするんですが、多分UltimateやProfessional、Enterpriseにも適用できるんです。
で、使っているOSがHome Premiumであるかどうかに関係なく、パッチ当てると当てる前に比べてちょっとイイコトがあるんです。

恒常的にRDPを使用している方なら知っていると思うんですが、現在のWindowsはマルチユーザログインできるのに対して、リモートデスクトップでWindowsに接続しようとすると既にログインしているアカウントはログオフしなくちゃいけません。
しかしこのパッチで"Enable multiple logons per user"というオプションを有効にすることで、ユーザごとに別々のセッションを割り当てることができるためこれを解消できます。
これは便利やでぇ・・・!

パッチのご紹介


まずダウンロードリンクからZIPファイルをダウンロードして解凍してください。

[For Windows 7 SP1 (x86/x64)]
Concurrent_RDP_patcher

解凍して出てくるexeを実行すると以下のようなウインドウが表示されます。
適切なオプションにチェックを入れて[Patch]ボタンを押すと、もう完了です。アラ簡単!
オプションの説明も書いときましょう。yu1rowって親切!

オプション説明
Enable multiple logons per user前述の通り、ユーザ毎に別々のセッションでログオンできるようにします。
既にログオンしているユーザがログオフにされることは無くなります。
ただし、マシンパワーが無いとすごくPCが遅くなるかもしれません...よ?
Enable blank password logonsパスワード無しのログオンを有効にします。
ただしセキュリティ的に如何なものかと思いますので、これを有効にする人は少ないでしょう。

注意点


  1. 前述のパッチが当たらないよー!って場合、DLLのバージョンが変わってたりすることが考えられます
    2012/07/06時点では上記パッチが使用できましたが、今後のWindowsアップデート次第ではどうなるかわかりませんのでご注意下さい
  2.  RDPのサーバ側はTCP/UDPの3389番を待ち受けポートとして使用しますファイアーウォールやルータのNAT設定などで受信ポートを空ける設定をしないと接続できない場合がありますのでご注意下さい
    設定方法は...環境によっていろいろなんで、各自で調べて下さい
以上です!

2012年7月5日木曜日

JNIお急ぎ作成レシピ

JNIる


こんにちは。イチ、プログラマのyu1rowです。
JavaでOSネイティブの機能を使用する際に使用するJNIってものがあります。
何それウマイの?って人は立ち去って頂いても結構です。

JNIは使おうとするとやり方を忘れちゃったりしてたりするんで、足がかりになるくらいの備忘録を残しておきます。

前提条件として必要な環境


OSWindows
(今回はWindows 7 Professional x86を使用)
IDE(Java)Eclipse
(今回は3.6 Helios SR2 x86を使用)
IDE(C/C++)Visual Studio
(今回は2005 Professionalを使用)
JDK今回はjdk1.6.0_24を使用
環境変数上記JDKにパスが通っていること
(上記のデフォルトならC:\Program Files\Java\jdk1.6.0_24\bin;とか)

それでは、以下つらつらと流れを書いていきます

Step 1 : JNI呼出用クラスの作成~ヘッダファイルの生成


まずはEclipseを起動してクラスを作成します。

今回はクラス名を"JniSample"としています。
後でDLLを作成するとして、DLL名称は"JniSampleImpl.dll"とでもしましょうか。
int型の引数を渡せる戻り値voidの"ExecSample"というメソッドを作ることにします。
ソースコードのダウンロード

classファイルからヘッダファイルを生成します。
コマンドプロンプトを起動してeclipseで使用しているworkspaceの中の、作成したプロジェクトのフォルダの中にbinフォルダがあると思いますので、このフォルダに移動します。
ここでjavahコマンドに-jniオプション、先ほど作成したクラスの装飾名をフルで指定するとヘッダファイルが作成されるはずです。
前述のとおり、環境変数でJDKのインストール先にパスを指定していないとjavahコマンドが失敗します。

コマンドが成功するとこんな風にhファイルができているはずです。

Step 2 : DLLの作成 - プロジェクトの作成~ヘッダファイルの追加


Visual Studioを起動して新しいプロジェクトを作成します。
今回は"JniSampleImpl"という名前でWin32プロジェクトを作成しました。
アプリケーション設定で、「アプリケーションの種類」を「DLL」に、「追加のオプション」で「空のプロジェクト」を指定します。

プロジェクトのフォルダが作成されるので、Step 1で生成されたヘッダファイルをココへ移動します。
フォルダに移動したヘッダファイルをプロジェクトに追加します。

Step 3 : DLLの作成 - ネイティブコードの実装


実装を行うため、cppファイルを作成します。
今回は"JniSampleImpl.cpp"という名前でファイルを追加しました。

cppファイルでは生成したヘッダファイルのインクルードを記述し、ヘッダファイルの定義に従って関数を記述します。
以下の例では引数に1が渡されたらメッセージボックスを表示するように実装しています。
ソースコードのダウンロード

Step 4 : DLLの作成 - JNI用ヘッダファイルのインクルードパス設定


※Visual Studioで1度設定しておけば以後はもう一度行う必要はありません
JDKをインストールしたフォルダのincludeフォルダと、さらにその中のwin32フォルダをインクルードする対象のフォルダに設定しておきます。
「ツール」メニューの「オプション」で開くダイアログから「プロジェクトおよびソリューション」の「VC++ディレクトリ」を選択すると設定を行う画面になります。
ここで2つのフォルダを追加しておきます。

Step 5 : DLLの作成 - ビルド前の設定~ビルド


プロジェクトの設定でランタイムライブラリの設定を行っておきます。
共通DLL設定でDLLを作成した場合、作成されるDLLのファイルは小さなサイズにすることができますが、ランタイムライブラリがインストールされていない環境では実行することができません。
設定を変更してランタイムライブラリをDLLに埋め込むようにしておきます。
左側のペインの「構成プロパティ」→「C/C++」→「コード生成」を選択し、右側の「ランタイムライブラリ」で「マルチスレッドDLL(/MD)」を「マルチスレッド(/MT)」に変更します。
※Debugの場合、「マルチスレッドデバッグDLL(/MDd)」を「マルチスレッドデバッグ(/MTd)」に変更します
設定が完了したら「ソリューションのビルド」を行います。
正常終了した場合、"JniSampleImpl.dll"が出来上がるはずです。

Step 6 : EclipseでのDLL指定~実行


Eclipseに戻り、先ほど作成したDLLをプロジェクトにインポートします。

「実行構成」からDLLを追加した場所を環境変数に追加します。
「実行」をクリックでアプリケーションが開始されます。
うまくいけば先ほどのDLLが呼び出され、ダイアログが表示されるはずです。


お疲れ様でした


手順は以上となります。
ねっ?簡単でしょ!?とまでは言いませんが、慣れれば何てことはないと思います。