メモの日々


2012年08月02日(木) [長年日記]

[サッカー] ロンドンオリンピック 男子 日本vsホンジュラス (コベントリー)

トーナメント進出を決めている日本は控え中心のメンバー。

                                        杉本(C大阪)
             斎藤(横浜FM)             大津(ボルシアMG)       宇佐美(ホッフェンハイム)
                       山村(鹿島)                        山口(C大阪)
酒井高(シュツットガルト) 吉田(VVVフェンロー)    鈴木(新潟)        村松(清水)
                                        権田(FC東京)

ホンジュラスはメキシコの右下にある小国。スペインに勝ってきており強い。ホンジュラスがゲームを支配するが、日本の守備も悪くなくシュートまではいかせない。始めは日本の選手達に硬さが見られたが、徐々に調子が出てきた。山口の動きが良い。山村は力が抜けててやる気なさそうに見えちゃうけど、次第にボールを繋げるようになっていた。村松も厳しいかと思ったが、前半終わりにはいい飛び出しを見せた。権田は危ないシュートを何度か防いだ。杉本宇佐美は仕事をできず。

後半は日本ペース。山村の攻撃参加いいね。大津も頑張っている。が、日本もシュートまではなかなかいけない。杉本を清武へ、斎藤を永井へ、大津を東へ交代。吉田の安定感素晴らしい。酒井高はドイツではいいようなのに代表ではいつもイマイチ。バタバタしているように見えるんだよなあ。この試合も引き分けOKで、最後はパスを回すだけの試合になってしまった。ホンジュラスのキャプテンがクリスチアーノロナウドに似ていた。


2012年08月03日(金) [長年日記]

  • 新しい仕事は皆Eclipseを使っているようなので、久しぶりにインストールしてみた。今のバージョンは4.2。フォントなど色々設定したのだけれど、Vrapperが未だに矩形選択をサポートしていないことに気づいて使う気が無くなってしまった。最初にそこをチェックすべきだった。
  • ので、NetBeansに戻る。今まで7.0.1を使っていたが、7.2をインストールしてみた。jViが使えるか心配だったんだけど、ちゃんと動いているようだ。

[java] システムアイコンの取得

UIManager.getIcon("OptionPane.questionIcon");

のようにして、既存のSwingコンポーネントが使用しているアイコンを取得できるということをメモ。でも、使用可能な名前に何があるかはわからない。

[サッカー] ロンドンオリンピック 女子 準々決勝 日本vsブラジル (カーディフ)

トーナメントの1回戦。日本の先発は初戦2戦目と同じ。ブラジルはマルタなど。解説は宮本。冷静でいいね。

開始すぐに大野の惜しいシュートがあったが、その後は一方的にブラジルが攻める。大儀見も今回はなかなかキープができない。コーナーキックを何本も蹴られた。危ないロングシュートなどもあったが何とか凌ぎ、20分過ぎからは日本も攻めることができた。ここから日本ペース。宮間がゴール前のチャンスで滑って持ち直してシュートしたり。そして、30分近く、澤の素早いフリーキックから大儀見がDFの裏へ抜け出し落ち着いてシュートを決めた!その後は一進一退。今日も澤がよくて、彼女のパスからチャンスを作っていた。

後半もブラジルが支配。日本は中盤で奪えずゴール前で跳ね返すことしかできない。ボールを取れたら前線の大儀見にロングパスを送るが、ブラジルの奪取力高くそうそううまくいくものではない。んが、後半またも30分近く、大儀見が左サイドでボールを受けてうまく相手の裏を取り、そこから素早く中央の大野へミドルパス。大野はダイレクトシュートのチャンスを逃しDFに詰められてしまうが、冷静にコースを見つけてシュート。これがGKの上を超えてバーに当たって入った!GKが届かない所への素晴らしいシュートだ。大野が点を取るのを観るのは久しぶりだなあ。よかった。その後大野を安藤へ、大儀見を高瀬へ交代。

その後もブラジルに攻められ続けるが、粘り強く守って勝った。ベスト4進出。


2012年08月04日(土) [長年日記]

[サッカー] ロンドンオリンピック 男子 準々決勝 日本vsエジプト (マンチェスター)

日本の先発は初戦と同じ。

立ち上がりは日本ペース。エジプトに攻撃させず、清武を中心に相手ゴールへ何度か迫る。東髪切ったな。15分頃、右サイドで清武がボールを奪って裏へ抜けると昨日の大儀見のように素早く中央の永井へパス。GKが突進してくるが永井は胸で右側に落とす。GKは味方DFと激突。がら空きのゴールへ永井が流し込んだ。永井ブレークしたな。が、シュート後に相手DFとぶつかった永井は左太腿を痛めて交代してしまった。替わって入ったのは斎藤。

その後はエジプトが攻勢をかける。徳永のサイドにボールを集め力強い突破をしてくるが、日本は跳ね返し続ける。そして40分、またボールを奪った清武が素早く右サイドの東にパス、東はダイレクトで中央へパス、そこへ走りこんだ斎藤を後ろからエジプトDFが倒し、レッドカードで退場に。主審はスペイン戦と同じだそうで。それで得たエリアギリギリからのFKは扇原が蹴ったが壁に当たってダメ。

後半、日本のパスがよく回る。今日はミスがない。途中で東が足を捻り、プレーを続けたが結局酒井高と交代した。後半30分過ぎ、右サイド深い所からのFKを清武が蹴り、ニアで吉田が頭で合わせてゴール。その後エジプトの巨体DFヘガジーが足を痛めて退いてしまう。エジプトは交代選手を使い切っており9人で戦うことに。やりにくいなあ。後半40分頃、左サイド深い所からの扇原のクロスを中央の大津がヘディングで綺麗に決めた。清武を宇佐美に交代。そして試合終了。男子もベスト4進出だ。


2012年08月05日(日) [長年日記]

[java] Javaでスクリーンショットを撮る

スクリーンショットを撮ることはJavaだけでもできるんだな。java.awt.Robotクラスを使えばよい。

デスクトップ全体のスクリーンショットをPNGファイルに出力するサンプルをメモ。

package sample;

import java.awt.AWTException;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;

public class ScreenShot {
    public static void main(String[] args) throws AWTException, IOException {
        Robot robot = new Robot();
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        BufferedImage image = robot.createScreenCapture(
            new Rectangle(0, 0, screenSize.width, screenSize.height));
        ImageIO.write(image, "PNG", new File("screenshot.png"));
    }
}

2012年08月06日(月) [長年日記]

[サッカー] ロンドンオリンピック 女子 準決勝 日本vsフランス (ロンドン)

勝てばメダル確定の準決勝。相手は直前の親善試合で完敗したフランス。日本の先発は前の試合と同じ。

立ち上がり10分までは日本が支配。ずーっと攻めていたがシュートまではいけない。10分にフランスにチャンスがきて、その後は一進一退。日本はあまりリスクを負わずDFに戻してやり直すことが多い。フランスが日本のDFにプレッシャーをかけてこないので楽だ。しかし守備を固めるフランスに対し全くシュートを打てない。対するフランスはパワーとスピードで突破してきて何度かシュートを打ったが、工夫がなくそれ程怖くない。そして30分、距離のあるFKを宮間が力強く蹴り、それをGKが弾いてしまう。そこへ大儀見がしつこく詰めてゴールへ押し込んだ。その後はフランスも攻めてくるが日本は守備に人数をかけて守る。前半は守りあいの退屈な試合。日本のシュートは1本だけだった気がする。

後半、3分に再び宮間の遠目のFKを阪口がDFの間に上手く入ってヘディングで素晴らしいシュートを決めた。その後、川澄のパスを受けた大野がエリア内で自分の切り返しに自分で対応できずコケたり。フランスは2人を交代をして調子が出てきた。日本は下がり過ぎなのか、一方的に攻められてしまう。フランスはらしいパス回しからシュートの雨あられ。日本は福元の左手一本でのキャッチなどで凌いでいたが、後半30分、鮫島のサイド深い所から速いクロスを上げられゴール正面からボレーシュートを決められてしまった。そのすぐ後にはエリア内で阪口が相手を倒してしまいPK献上。しかしそのPKをフランスはゴール右へ外してしまう。日本は失点前に大野を安藤へ交代していた。しかし安藤は攻撃で機能せず、大儀見頼みだけではうまくいかず日本は全く攻められない。全く攻められないー。阪口を田中に代えて守備の立て直しを図るが、フランスは長身ルナールを前に残してパワープレイ。やられるのは時間の問題だ、と思った後半45分に大儀見がDFの裏に抜けGKと一対一に。上手いシュートを打ったが右のバーに当たって入らず。その後何とか凌ぎ切って決勝進出。


2012年08月07日(火) [長年日記]

[サッカー] ロンドンオリンピック 男子 準決勝 日本vsメキシコ (ロンドン)

卓球女子団体決勝日本vs中国を観ていたのでこの試合の最初は観ていない。福原vs李暁霞、石川vs丁寧、石川平野vs李暁霞郭躍。日本選手の出来はよかった。

日本の先発は前の試合と同じ。怪我をしていた永井も出場している。

前半10分過ぎ、大津がコール正面やや左からゴール右隅にレーザービームミドルシュートを決めた。すごいシュートだった。日本はパスがよく回り強い。山口の姿勢がよい。しかし30分にコーナーキックから決められたー。これが今大会初失点。メキシコも強い。メキシコペースで前半終了。

後半もメキシコ優勢。20分、スロー再生中に扇原がゴール前でボールを奪われてしまい、そこからゴール上隅へゴールを決められてしまった。初めて追う展開に。こうなったときのオプションで、東に代えて杉本を、清武に代えて宇佐美を投入。しかし日本は形を作れない。東清武不在は大きいか。更に扇原に代え斎藤。吉田を前線に上げてパワープレー。が、ロスタイムに逆にメキシコに左サイドを突破され得点されてしまった。


2012年08月10日(金) [長年日記]

[サッカー] ロンドンオリンピック 女子 決勝 日本vsアメリカ (ロンドン)

日本時間午前3時45分キックオフ。日本の先発は準決勝と同じ。アメリカの先発は

        モーガン    ワンバック
    ヒース                 ラピノ
      ボックス        ロイド
オハラ ビューラ ランポン ルペルベット
              ソロ

立ち上がり、アメリカは日本のDFにプレッシャーをかけてくる。そして8分、近賀のサイドからヒースがクロス、それをゴール前でモーガンが左に流してゴール前フリーのワンバックに折り返し、それを決められたー。ワンバックが決めたと思ったけど、スローで観ると後ろからロイドが走りこんで決めていた。ロイド見えなかった。

日本はラストパスが合わずにシュートまで至らなかったが、左サイドで川澄が基点となり徐々にチャンスを作る。澤のパスから川澄がエリア内に侵入してシュート、DFに弾かれた所を大儀見がシュートもゴール左へ。澤の落としを川澄がクロス、大儀見がうまくヘディングするがソロに弾かれポストに当たる、倒れていた大儀見素早く立ち上がって再びシュートするがゴール右へ。川澄のパスからエリア内で大野がシュートチャンスもシュートできず、右に横パスして走りこんだ宮間がシュートもバーに当たる。エリアの少し外で大儀見が落としたボールを大野がシュート、僅かにゴール右へ。あと少し。サイドバックがうまく攻撃に絡めないなあ。

後半。8分過ぎにロイドがドリブルで突進、エリア外正面右からゴール左へミドルシュートを決めた。いいシュート。2点を追う日本は阪口を田中に交代。意図は?日本も20分頃、右サイド宮間からのパスを大野が中へ折り返しフリーの澤がシュート、跳ね返りを再び澤、そのボールが流れてきた所を大儀見がゴールに押し込んだ。鮫島を岩渕に交代し勝負をかける日本。岩渕はDFからボールを奪ってGKと1対1でシュートを放つがソロに弾かれた。もう後半40分。大野を丸山に交代。その後はチャンスなかったなあ。交代って難しい。

大会通じて良かった順に、大儀見熊谷岩清水福元澤川澄大野阪口宮間近賀鮫島。大儀見頼みの攻撃に大儀見が良く答えた。サイドバックは印象薄い。

[java] ConcurrentHashMapのSet版

「取得の完全な同時性および予想される調整可能な更新平行性をサポートするハッシュテーブル」であるConcurrentHashMapに対応するConcurrentHashSetというクラスは用意されていない。

そいうSetを得たいときは、Collections#newSetFromMap()を使って

Set<String> concurrentSet = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>());

などとすればよさそう。でも、これだとConcurrentMapインタフェースにあるメソッドは使えない。Setは諦めてConcurrentHashMapをそのままSetのつもりで使う方がいいケースもありそう。


2012年08月11日(土) [長年日記]

[サッカー] ロンドンオリンピック 男子 3位決定戦 日本vs韓国 (カーディフ)

3位決定戦の相手は韓国。日本の先発は変わらず。韓国はキム・ボギョン、ク・ジャチョルなどで監督がホン・ミョンボ。解説は福西。辛口解説をお願いしたい。

立ち上がりは韓国が押し込んだが、その後はロングボールを蹴っては跳ね返すことを交互に繰り返していた。芝の状態がよくないようで、選手が滑る滑る。徐々に日本がパスを繋げるようになり、何度かチャンスを作った。が、37分、映っていない所で韓国のロングボールが前線のパク・チュヨンに通ってしまい、鈴木と1対1に。すぐに日本DFも戻ったが、パク・チュヨンが右にかわしてゴール右へシュートを決めた。パク・チュヨン上手いなあ。彼はオーバーエイジ。

後半。日本はパスは回るがシュートにいけない。10分過ぎ、韓国またもロングボールからク・ジャチョルが抜け出しゴール左へシュートを決める。この決定力いいなあ。扇原に代えて山村。山村は積極的にゴールへ向かうパスを出していた。東を杉本に交代。杉本は機能せず。永井を諦め宇佐美投入。宇佐美はいいドリブルもあったがはまらない。岩渕状態。時間のない日本はロングボールを放り込むが韓国に跳ね返され続ける。杉本の高さが全く生きないぞ。40分過ぎ、宇佐美のCKを吉田が決めたが、その前に大津がGKを倒していてゴールにならず。うーん。

男子の評価順は吉田大津永井山口清武東鈴木権田徳永扇原酒井だな。吉田はDFリーダとしてチームをまとめた。最後の2試合は調子悪そうだったけど。大津永井もよく頑張った。男子もサイドバックが活躍できなかった。酒井は悔しいだろうなあ。


2012年08月18日(土) [長年日記]

[dev][c] gccの-lオプションを指定する位置

gccでライブラリを指定する-lオプションは、その指定する順番が重要なことを理解していなかったのでメモ。

gccのマニュアル(リンク切れ → gccのマニュアル)の-lオプションの説明に次のようにある。

       -llibrary
       -l library
           (省略)

           利用者がコマンドで、このオプションを書くところで違いを生じます。リ
           ンカは、ライブラリとオブジェクトファイルが指定される順序でそれらを
           検索して処理します。したがって、foo.o -lz bar.o は、ライブラリ z を
           ファイル foo.o の後で、bar.o の前に、検索します。bar.o が z 中の関
           数を参照しているなら、それらの関数はロードされません。

-lで指定するライブラリ内の関数をロードしたくないケースはあまりないと思うので、通常は-lオプションは後ろの方に書くのがよさそう。

試しておく。次の3つのファイルを用意。

  • main.c
#include <stdio.h>
#include "one.h"
int main() {
    printf("one=%d\n", one());
    return 0;
}
  • one.h
int one();
  • one.c
#include "one.h"
int one() { return 1; }

オブジェクトファイルとライブラリファイルを作成。

$ gcc -Wall -c *.c

$ ar -r libone.a one.o
ar: creating libone.a

-lオプションをmain.oの前に書くとリンクエラーになるが、後に書けば大丈夫。

$ gcc -L. -lone main.o
main.o: In function `main':
main.c:(.text+0xa): undefined reference to `one'
collect2: ld はステータス 1 で終了しました

$ gcc -L. main.o -lone

$ ./a.out
one=1

2012年08月19日(日) [長年日記]

  • 古江が大企業の幹部になっている夢をみた。

[java] JNIを使う

JNIを使ってみたので手順をメモ。Windows上で、MinGW-w64を使ってネイティブコードの実装を行う。

  1. ネイティブメソッドを持つクラスの作成 (Java)
  2. ヘッダファイルの生成 (Java)
  3. ネイティブメソッドの実装 (C++)
  4. 共有ライブラリの作成 (C++)
  5. 実行 (Java)

ネイティブメソッドを持つクラスの作成 (Java)

package sample;

public class NativeCounter {
    private int value = 0;
    public native int add(int i); // これをC++で実装する。

    public static void main(String[] args){
        NativeCounter counter = new NativeCounter();
        counter.add(100);
        System.out.println(counter.add(100));
    }

    // ライブラリのロード処理。
    static {
        System.loadLibrary("counter");
    }
}

add()がネイティブメソッド。native修飾子を付けて、実装はなしにする。

ネイティブメソッドを使えるようにするには後で作成する共有ライブラリをロードする必要があるので、System.loadLibrary()によりそれも行っている。

ヘッダファイルの生成 (Java)

javahコマンドを使うと、ネイティブメソッドの実装に必要なヘッダファイルを生成できる。

> javah -cp . sample.NativeCounter

これでカレントディレクトリに sample_NativeCounter.h が生成された。なお、javahの -stubs オプションは機能しないみたい。

ネイティブメソッドの実装 (C++)

生成された sample_NativeCounter.h に合わせて sample_NativeCounter.cpp を次のように書いてみる。

#include "sample_NativeCounter.h"

JNIEXPORT jint JNICALL Java_sample_NativeCounter_add(
        JNIEnv *env,
        jobject obj, // JavaのNativeCounterオブジェクトを指す
        jint i) {
    // NativeCounter#valueフィールドを取得
    jclass objClass = env->GetObjectClass(obj);
    jfieldID valueField = env->GetFieldID(objClass, "value", "I");

    // フィールドを取得できない場合は例外が投げられているはず。速やかに
    // returnするとJava側では戻り値ではなく例外を受け取る。
    if (!valueField) return 0;

    // NativeCounter#valueフィールドの値の取得と更新
    jint v = env->GetIntField(obj, valueField);
    jint result = v + i;
    env->SetIntField(obj, valueField, result);

    return result;
}

ネイティブコード内でのJavaとのやりとりはJNIEnvクラスが持つメンバ関数を介して行える。使える関数はここで分かる。

手元の環境だとjint型はlongのtypedefだった。

共有ライブラリの作成 (C++)

上述の通り、MinGW-w64のg++を使って共有ライブラリを作成する。MinGW-w64ではなくMinGWの方のウェブサイトにJNI-MinGW-DLLというページがあったので、ここに従って

> g++ -Wall -D_JNI_IMPLEMENTATION_ -Wl,--kill-at ^
  -I"%JAVA_HOME%\include" -I"%JAVA_HOME%\include\win32" ^
  -shared -o counter.dll sample_NativeCounter.cpp

とした(コマンドプロンプトで実行)。_JNI_IMPLEMENTATION_ の定義の必要性は理解していない。jni.h内で使われているが、定義しなくても動作した。-Wl,--kill-at は必要で、これがないとJavaからDLL内の関数を見つけられなかった。

実行 (Java)

作成したNativeCounterクラスの実行時には、上で作った counter.dll をロードできるようにする必要がある。実行時にシステムプロパティの java.library.path に counter.dll が置かれているディレクトリを指定するのが一つの方法。

> java -cp . -Djava.library.path=lib sample.NativeCounter
200

2012年08月20日(月) [長年日記]

[windows][c++] Windowsでアクティブウィンドウのタイトルを取得

MinGW-w64を使って、初めてWindowsプログラミングをしてみる。手始めにアクティブウィンドウのタイトルを取得してみた。JNIから使えるライブラリとして実装する。色々難しい。.net frameworkを使えばきっともっと簡単なんだと思う。

APIのリファレンス

APIの一覧を知りたいのだけれど、それが分かるページがよく分からない。一応、

から辿れそうなんだけど、APIリファレンスじゃないページも混じっていて頑張らないと見つけられない。日本語訳が

みたい。ここの「Windows 2000」の下をよく探すとカテゴリ毎にリファレンスが見つかる。

アクティブウィンドウを得る

GetForegroundWindowという関数でアクティブウィンドウのハンドルを得られる。これは簡単。

ウィンドウタイトルを得る

GetWindowTextという関数でウィンドウのタイトルを得られる。ウィンドウタイトルを保存する領域が必要になるので、事前にGetWindowTextLengthで文字数を調べる必要がある。

で、GetWindowText()の引数の型がLPTSTRとなっていて、これが難しかった。WindowsのAPIの実装というのはワイド文字版とマルチバイト文字版の2種類があって、その違いを意識しないために文字にはTCHARという型を使っているようである。LPTSTRというのは TCHAR* のことみたい。

で、TCHARがワイド文字(wchar_t)なのかマルチバイト文字(char)なのかは、UNICODEというマクロが定義されているかどうかで決まっている模様。

書いてみたら難しくなかった。

LPTSTRをJavaの文字列へ変換

JNIを使うので、GetWindowText()で得た文字列をJavaの文字列へ変換しないといけない。このときに、TCHARがワイド文字なのかマルチバイト文字なのかで処理を分ける必要がある。

Javaの文字列生成にはNewStringを使う。これに渡すパラメータは「Unicode文字列を参照するポインタ」とある(型はconst jchar*)。Unicode文字列ってのはUTF16のことなのかなあ。

ちゃんと理解していないのだけれど、Windowsのwchar_tはUTF16のようで、TCHARがワイド文字を表す場合はLPTSTRをjchar*へキャストしたものをNewString()へ渡すことでちゃんと文字列を得られた。

TCHARがマルチバイト文字を表す場合はMultiByteToWideCharというWindowsのAPIでワイド文字に変換すれば、上と同じくjchar*へキャストすることでJavaの文字列を得られた。

ワイド文字とマルチバイト文字の選択方法

MinGW-w64のFAQにUnicode applicationsというページがあって、

To compile Unicode applications, define _UNICODE and UNICODE in your files when compiling and add -municode when linking.

とあった。なので、ワイド文字モードにするには、コンパイル時に「-D_UNICODE -DUNICODE」を、リンク時に「-municode」をg++のオプションとして与えればよさそう。これらをしないとマルチバイト文字モードになるようだ。

ソースコード

アクティブウィンドウのタイトルを取得するJNI関数を書いたのでメモしておく。やっつけなので醜いです。あー、このままだとC++の例外発生時にJVMが終了してしまうので、せめて例外をcatchしておく処理が必要だ。

#include <windows.h>
#include <winnls.h>
#include "sample_Windows.h"

JNIEXPORT jstring JNICALL Java_sample_Windows_activeWindow(
        JNIEnv *env,
        jclass) {
    HWND handle = GetForegroundWindow();
    if (!handle) return env->NewStringUTF("");

    int length = GetWindowTextLength(handle);
    if (!length) return env->NewStringUTF("");

    LPTSTR buffer = new TCHAR[length + 1]; 
    length = GetWindowText(handle, buffer, length + 1);

    jstring result;
#ifdef UNICODE
    result = env->NewString((jchar*)buffer, length);
#else
    int wide_length = MultiByteToWideChar(CP_ACP, 0, buffer, -1, 0, 0);
    if (!wide_length) {
        delete[] buffer;
        return env->NewStringUTF("");
    }

    LPWSTR wide_buffer = new WCHAR[wide_length];
    if (!MultiByteToWideChar(CP_ACP, 0, buffer, -1, wide_buffer, wide_length)) {
        delete[] wide_buffer;
        delete[] buffer;
        return env->NewStringUTF("");
    }

    result = env->NewString((jchar*)wide_buffer, wide_length);
    delete[] wide_buffer;
#endif

    delete[] buffer;
    return result;
}

2012年08月31日(金) [長年日記]

[java] 64ビットWindows用JDKインストール時のレジストリ設定が変

自分は64ビットWindowsを使っていないので詳しいことは分からないのだけれど、64ビットのWindows 7に jdk-7u7-windows-x64.exe を使ってJDKをインストールすると、レジストリの

  • HKEY_LOCA_MACHINE
    • SOFTWARE
      • JavaSoft
        • Java Runtime Environment
          • 1.7.0_07

のRuntimeLibに「~\Java\jre7\bin\client\jvm.dll」と書きこまれるみたい。でも、このファイルは存在しない。存在するのは「~\Java\jre7\bin\server\jvm.dll」だ。

レジストリのここを見ているソフトが動かないので困る。