コミケ告知

サークル networkmaniacs.net(旧:浜風もっこす) 2017.02.17 デブサミ内 DevBooksに出展します。
詳細は circle タグの記事へ。
2013年2月28日木曜日

C# (VS2012)のプロジェクトからF#のライブラリを呼ぶための初歩

Visual Studio 2012 Express Editionを使って、C#のWindowsアプリからF#のライブラリを呼ぶ。…ということをやりたかっただけなのに。VS2012では、F#はVisual Studio Express for Web、C#のデスクトップアプリケーションは、Visual Stidio Express for Window Desktopの担当に分けられていて、無用にめんどくさかったです。

手順


Windows DesktopのWPFアプリのソリューション内に、F#のライブラリプロジェクトを作成!ができれば簡単だったのですが、どうも上手くいかず、現在のところ以下の手順でなんとかしています。

  1. for Webを使って、F#ライブラリプロジェクトを作成
  2. そのプロジェクトで出来たdllを、for Windows DesktopのC#プロジェクト内「参照設定」に追加
    • 参照設定→参照の追加で開いたダイアログ中の「参照」を押すとファイル選択ダイアログが出るので、選ぶ
      • ライブラリプロジェクト名のdllがDebugとかReleaseとかの下にあるはず
    • 同様にFSharp.core.dllも追加
 

fow Webの画面でF#をいじりつつ、for Windows Desktopの画面でWindowsアプリケーションをいじっています。どうにか1つに出来ないものかね…。

for WebでF#を動かすまでの話は少し前のポストの序盤に書いたので、あちらを参照で。
あれ?DebugとReleaseどっちを追加すればいいんだ?切り替えるには、プロジェクトファイルに手を入れないといけないようです。F#で遊んでいる段階では常時Debugビルドでもいいんですが。


プロジェクトを参照出来れば、こんなことをする必要はなく楽なのに。F#プロジェクトを含むソリューションを開こうとすると「このEditionではダメ」と言われてしまいました。出来る方法があったら知りたい。

  • (2013/02/24追記) F#ライブラリは、--standalone をコンパイラに渡すと、F#関係もバンドルされたdllを生成できる (C#側でFSharp.dllを別に読まなくても良い)

デバッグ

プロジェクトは分かれていても、for Windows Desktopの側からステップ実行したり、F#のソースにブレークポイントを張ったりできます。


F#で定義したところにステップインすると…

F#のソースがそのまま見えます。ブレークポイントも設置できます。普通にファイルを開いているだけなので編集もできますが、for Web上のF#ライブラリプロジェクトでビルドしないと反映されません。両側で編集しちゃうと危険。

技術的にはF#が混在することに全く問題なさそうだけれども、機能が潰されてる感じですね。普及段階なんだから、もうちょっとなんとかしてよ、と思います。
2013年2月23日土曜日

JRA公式Webのリンクに小細工するだけのChrome拡張

自作Chrome拡張は意外と難しくないことがわかったので、変な小物を色々と作っています。画像保存とか特定の文字列をコピペするとか、公開したくないようなものが多いですが。

今日は、JRA公式Webサイトのリンクの挙動を書き換えるものを作っていました。

目的


このWebサイト、官公庁なので仕方ないですが、少し古いつくりです。

通常のハイパーリンクと、JavaScriptで処理されるリンクが混在しています。通常のリンクは良いのですが、JavaScriptで処理されるリンクは、右クリックから「新しいタブで開く」を使おうとしても、新しいタブでは正常に開けず、エラーが発生します。さらに残念なことに、見た目ではこの2種類のリンクは区別がつきません。

関連する情報を並べることができないので、タブ一枚で進んだり戻ったりしながら閲覧するのに疲れたので、少し小細工するための拡張を作ることにしました。

構造

JavaScriptで処理されるリンクは、doActionという関数にパラメータが渡されるようになっています。中を見るとただのアンカーではなく、ページ内の隠しフォームにパラメータを入れて、GETではなくPOSTでデータをSubmitすることにより、次のページを開いているようです。

実装


Google先生に尋ねたところ、form.targetに開く先を指定できることがわかりました。リンクの開き方がわかれば、あとは通常動作と「新しいタブで開く」動作で分岐すればよさそうです。とりあえず、Ctrlキーを押しているかどうかを判定し、押されている場合は新しいタブで開くことにしました。

ついでに、あまり使わないけれども、shift同時押しでウィンドウが開くように。適当にターゲット名をでっちあげて、毎回違うウィンドウが増える仕様です。


Chromeの「拡張機能のパッケージ化」では、ディレクトリの中身をまるごと全部、つまりアイコン作成用の作業ディレクトリ&ファイルや、.gitまでまとめて固めてくれるみたいです。そのため、固めるように別ディレクトリを作り、必要なファイルだけそちらにコピーして固めるようにしています。

雑感

Chrome拡張、くだらないものが、それに見合った労力で作れるのが良いですね。ウェブストアに公開するような場合は、細かい作りこみが増えて大変なのかもしれませんが、自分用に作る分にはとても気楽です。
難点があるとすれば、JavaScriptは動的型付け言語のため、簡単なコードですらエラー箇所特定が大変なところです。Chromeのデバッグ環境はかなり強力ですが、それでもあまり大きなものは作りたくありません。
2013年2月20日水曜日

rvmのfirewall対策 (gitのプロトコル変更)

Ruby言語は自分では書かないし使うこともあまりないのですが、バージョンが依存があってめんどくさいので、複数のバージョンをひとつの環境内に共存させるのが割と定番みたいです。 そういった環境管理ツールのひとつがrvmなのですが、内部でgitを呼び出すときに、HTTPではない(ファイアウォールで閉じられていることの多々ある)ポート番号を使おうとする上にエラー処理が適当なので困ります。

debian# rvm install 1.9.3-head
Installing Ruby from source to: /usr/local/rvm/rubies/ruby-1.9.3-head, this may take a while depending on your cpu(s)...
Cloning from git://github.com/ruby/ruby.git, this may take a while depending on your connection...

タイムアウト処理が一切ないようで、接続できなければ永遠に待ちます。gitのプロトコルが使えないのに待っていても成功することはないので、どうにかします。 rvmの中をgit://という文字列で検索をかけたところ、rvmのディレクトリ/config/dbに設定があり、こいつの中身を置換すればいいようです。

git:/をhttps:/に一括置換したところ、うまくいきました。
2013年2月16日土曜日

F#談話室(2) に参加してきた

今年も何か新しい言語に触ってみたいと思っていたところに、ちょうど入門コースのある勉強会があったので、参加してきました。
みんなで一斉に進めていきましょう形式ではなく、各自好きなことをやる集まりです。時間も夕方のLT以外は特に予定なく。

自分はF#の最初の一歩から始めたかったため、主催の七誌さんがビギナー向けとして用意してくださっていた資料を見ながら進めました。到着が17時、場所を閉めるのが20時、その間約3時間の参加でした。

環境のセットアップ (VS2012 ExpressでF# + Windowsフォームが遊べるまで)

無料のExpressでは、F#を使うまでに追加の作業が必要でした。F#を推進する気なら、最初から使えるようにしておけばいいのに…
  • Visual Studio 2012 for Webをインストール
  • Web Platform Installerを使って、追加コンポーネントとしてF#をインストール
    • 検索窓にF#と入れると、それっぽいものが出てくる
環境としてはここまで。チュートリアルでは、C#の入門編でやっているようにWindowsフォームを表示させて遊びたいのですが、Visual F#のプロジェクトはライブラリとチュートリアルしか選択肢がありません。実用的には、ライブラリの利用のみが提示されている状態。
そこで、「F#のチュートリアルプロジェクトを作成し、元から書いてあるコードを抹消する」という方法により、F#でWindowsフォームの使えるプロジェクト構成を安直に入手することが出来る、と教わりました。

はじめての えふしゃーぷ

リバーシ(オセロ)のサンプルをいじって、ネット上の文法のリファレンスを見ながら、途中パワーユーザーの方のLTを挟んで、実質90分ほどかけて、なんとか自分で関数が書ける程度にまで進みました。(いきなりリファクタリングっぽいところから入る性分もどうかと思いますが…)
以下がそのコードです…と丸ごと貼るには少々長かったのでリンクのみ。
https://gist.github.com/moccos/4967078

  • 自作の関数を書いた
    • 関数の引数に型が指定した
  • enumっぽいもの(?)を使った
  • if式、match式を覚えた
  • for構文を使った
  • 配列を使い始めた  (まだよくわかっていない気がする)
こんな状態です。石をひっくり返すロジックがないので、まだリバーシではなく石置きですね。

間違えたところ

  • 関数の引数に型指定するとき、カッコをけちって失敗
  • 関数呼び出すときに、引数足りなくて失敗
後者、C言語やJavaならば「そんな関数/メソッドないよ」というコンパイルエラーが出るところですが、F#は部分適用が効くので、違った形でエラーが現れます。boolを返す関数 myfunc x y を用いて if (myfunc 1) then ... と書くと、「boolじゃなくてint->boolがあるので型がおかしいよ」と言われるわけです。
ここでmyfuncの返り値を真っ先に疑ってしまいました。関数型言語そこそこに使っているのに、これは恥ずかしい…(゚Д゚)

雑感

わりと無難な感じでF#の第一歩を踏み出せたような気がします。F#でいきなり何か作るのは難しくても、C#のプロジェクトの一部にF#のライブラリを混ぜ込むような感じで、徐々に浸食していけるように頑張ります。

言語自体については…mutableな変数が簡単に定義でき、クラスの概念があるので、Scalaと似たような立ち位置になるのでしょうか。JVMに対する.NET、Javaに対するC#、Scalaに対するF#、と。
ML系の言語が初めてなので、不慣れな文法や演算子にびっくりしながら進めてました。Erlangのときも、文法にはなかなか馴染めなかったので、新しい流儀に入るときはこんなものでしょうかね。全く抵抗を感じさせなかったScalaのすごさを改めて感じました。


2013年2月13日水曜日

PARTAKEのタイトルを書きなおすだけのChrome Extension

# はてなダイアリーから移動した記事です。あまり真面目に整形していません。

なぜかイベントページのタイトルが PARTAKE になってしまうpartake.in。何度かいらっとしたので、くだらないChrome拡張を作りました。

最初はgithubに置いてみましたが、これを続けて改良していくことはないだろうし、PARTAKEがまともになれば(あるいはサービス終了すれば)それで終了な一時的なネタなので、gistに移しました。
バイナリ(PartakeTitleCorrector.crx)をChrome拡張画面にドロップすればインストールできるはずです。

実体は、ほぼ定型のコンフィグレーションファイル(manifest.json)と、1行のjavascript。やる気のないアイコンを用意する時間の方が長かったくらいかもしれません。これくらいの分量で動くなら、くだらん自分専用の拡張機能を色々作る気になります。

document.title = "PARTAKE: " + document.body.getElementsByTagName("h1")[0].innerText;

そもそもの問題として、PARTAKEの中の人ならば、TITLEタグの修正はあっという間に終えられるはず。タイトルがおかしいなんて、顔色変えて即修正するレベルの問題では?いったいどうなっているのでしょうか。もはや改良する気はなくて、売却に夢中だったりして?

# 13/02/14追記 バージョン指定が間違っていて、開発版にしかインストールできないので修正しました

2013年2月9日土曜日

RxJavaをScala(+SBT)から試してみる

# はてなダイアリーから移動した記事です。あまり真面目に整形していません。

C#のReactive ExtensionsのJava版*1であるRxJavaが、NetflixからApache License Version 2.0で公開されていました。

Rxについては

SBTのコンフィグレーション

rxjava-scalaへの依存性を書けばOK。依存しているrxjava-coreも取ってきてくれるので。

libraryDependencies += "com.netflix.rxjava" % "rxjava-scala" % "0.5.+"

最初見たときは0.5.0でしたが、今見たら0.5.1でした。

動作確認

ScalaAdaptorでテストに使われているサンプルほぼそのまま*2。くだらないけど、これが動かなければ設定がおかしいので、まずはここから。

    Observable.toObservable("1", "2", "3").take(1).subscribe(Map(
      "onNext" -> ((callback: String) => {
        println("testTake: callback = " + callback)
      })
    ))
run
[info] Running info.moccos.Main
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
testTake: callback = 1

動いているようです。
SLF4Jが邪魔ですが、ログは今は出なくてもいいので見なかったことに。(以後のログでも省きます)

java.lang.RuntimeException: Unsupported closure type というエラー

サポートしていない型をObservable.toObservableに渡すと、そんな型知らんとRuntimeExceptionを飛ばされます。最初、rxjava-core(ScalaのAdaptorがない)を引っ張ってきていたときに遭遇しました。

もう少し使ってみる

    val xs = 1 to 10
    Observable.toObservable(xs)
      .take(3)
      .subscribe(Map(
        "onNext" -> ((x: Int) => {
          println("testTake: callback = " + x)
        })
      ))
[info] Running info.moccos.Main
[error] (run-main) java.lang.ClassCastException
java.lang.ClassCastException
[trace] Stack trace suppressed: run last compile:run for the full output.
java.lang.RuntimeException: Nonzero exit code: 1
        at scala.sys.package$.error(package.scala:27)
[trace] Stack trace suppressed: run last compile:run for the full output.
[error] (compile:run) Nonzero exit code: 1

ぬ?
ここでonNextで拾う型をとりあえずAnyにしてみると…

testTake: callback = Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

お、おう。テストコードにあったようなtupleだと、ScalaAdapterが直接変換してくれて上手くいきますが、コレクションの変換はまだ実装されていないみたいです。明示的にJavaの理解できる型を渡してあげないと。

    val xs: java.util.List[Int] = 1 to 10

または

    Observable.toObservable[Int](xs)
[info] Running info.moccos.Main
testTake: 1
testTake: 2
testTake: 3

これはOK。ちなみにStreamの無限数列を渡したら、無限に数えます。push型=値を生成できる限りどんどんpushするのだから、そりゃ当然か。

使える操作

rx-coreのpackage rx.operatorsを見ればわかりそうです。

参考までに本家Rxのものは…もう2年半前で古い記事ですがこれを。

合成したり取得する値を選んだりという基本中の基本だけ備わっている状態です。それから、onCompletedって書いても動いてくれないみたい。まだ趣味プロジェクトの範囲内かなあ。時間系が入ってくると面白いんですが。
pull requestにあるように、Netflixの狙い通り(?)にいくつか飛んできているので、興味を持った人たちによってじわじわと増えるのでしょう。*3

雑感

生まれたてです。既に実戦投入されたものを公開したわけではないので、これからみんなでがんばろうぜ!と煽っている段階ですね。
Scalaだと、Akka発のFutureが強力だし、元々マッチングも手軽に色々できるので、rxjavaすげー!世界が変わる!ということにはならないかもしれませんが、今後どうなるのか楽しみではあります。

*1:JVM版と呼ぶべきかどうか

*2:テスト文取って改行を足した。

*3:お前も参加しろと言われると、力不足ですまんと答えるほかない…

2013年2月6日水曜日

Raspberry Piでboostの使えるクロスコンパイル環境を構築

# はてなダイアリーから移動した記事です。あまり真面目に整形していません。

Raspberry Piはいいハードウェアですが、これの上でコード書いたりコンパイルしたりというのは大変です。入出力が弱いこともあって、C++のSTLやboostのヘッダをincludeすいると悲しいことになります。GNU screenの上に妙なプラグインがいくつも走るVimをたくさん開く開発スタイルもきつそう。

distcc(分散コンパイル環境)を走らせれば…と一瞬思いましたが、Raspberry Pi上のリソースを使う意味が皆無なので、まっとうなPCの上でクロスコンパイルすることにしました。

試した環境

Windows上で走っているVirtualBox内の、64bitのDebianです。

Linux version 2.6.32-5-amd64 (Debian 2.6.32-46) (dannf@debian.org) (gcc version 4.3.5 (Debian 4.3.5-4) ) #1 SMP Sun Sep 23 10:07:46 UTC 2012

クロスコンパイル環境の構築

参考記事:How to build a cross compiler for your Raspberry Pi | Chris's Digital Realm
多少のバージョン番号の違いはあれど、上記記事の箇条書きに従って進めれば、あっさりとクロスコンパイル環境が出来ました。

微妙にはまったところは…

  • ディスク容量は4GBでは足りなかった
    • 仮想マシン等でディスク容量が限られる場合や、RAMディスク上で済ませようとする場合は注意
  • C++を使いたい場合は、参考記事の手順では足りない
    • コメントにある通り、C-compiler → Additional supported languages and enable C++を有効にする
  • rootユーザーで作業しないこと

rootユーザーについては、ct-ng menuconfig内に警告文があります。以下引用。

You normally do *not* need to be root to build a toolchain using crosstool-NG.
In fact, it is *VERY* dangerous to run as root, as crosstool-NG will, as part of the build process, remove a few directories.
If anything goes wrong, running as root can ruin your host distribution.

変な設定してrootで走らせると、OSごとまともに動かなくなる可能性もあるよ!という警告。警告文があるだけでなくて、何か所かそれっぽい設定にチェックを入れないと実行も出来ません。

全てが無事終わると、/opt/cross/x-tools/arm-unknown-linux-gnueabi/bin 以下に、arm-unknown-linux-gnueabi-xxx といった名前のものがごろごろしているので、これらを用いればあっさりとクロスコンパイルが出来ます。

% arm-unknown-linux-gnueabi-gcc main.c
% file a.out a.out: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 3.7.3, not stripped

boostの準備

ヘッダだけで済むものは何の苦労もないですが、ライブラリをリンクする必要のあるものはboostをビルドする必要があります。たぶん。
めんどいので完成品をいただきました。
Raspberry Pi • View topic - Boost C++ libraries for Raspberry Pi

適当なコードを書いて…

#include <stdio.h>
#include <unistd.h>
#include <boost/thread.hpp>

int main(int argc, char **argv) {
  bool enabled = true;
  boost::thread th1([&enabled](){
    while (enabled) {
      printf("hoge!\n");
      sleep(1);
    }
  });
  getchar();
  enabled = false;
  return 0;
}

適当に必要なパス情報を与えてコンパイル。-Lのパスは必要なもの(*.so)を置いた場所によりけり。この場所に置くのが妥当がどうかは知らないけども…

% arm-unknown-linux-gnueabi-g++ -std=c++11 bthread.cpp -I/usr/include -L/opt/cross/x-tools/arm-unknown-linux-gnueabi/lib -lboost_thread

scpでRaspberry Pi上に送って実行。Raspberry Piの環境には、apt-getでboostのライブラリを導入してあります。
raspberrypi ~% ./a.out
hoge!
hoge!
hoge!

動いた。本日ここまで。

2013年2月3日日曜日

GNU findの-regextype指定をどうにかうまく出来ないか

GNU findで正規表現を使いたい場合、デフォルトはエスケープがたくさん必要で使い勝手の悪いemacs正規表現です。というところまでは以前調べました。

毎回-regextype posix-egrepと打つなど本末転倒なので、findとタイプして呼び出すだけで自然についてきて欲しい。そこでまずは、安直にシェルのaliasで解決しようとしました。

alias find='find -regextype posix-egrep'

これで安心と思いきや、探索先のパスを指定すると…つまりカレントディレクトリ以外から探そうとすると動きません。

(上記aliasのfind)
% find ./hoge -regex ".*\.(h|cpp)"
find: paths must precede expression: ../
Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression]

パスは、-regexや-regextypeより前に置けと。エイリアスを使わない形で書くと、次のような形式が正しいようです。

% find ./hoge -regextype posix-egrep -regex ".*\.(h|cpp)"

それならば、最初の引数だけ前の方に動かすシェル関数でも書くか、と次に思いました。簡単な検索ならばそれでOKですが、まだ問題があります。Usageに示されているように、パスよりも前に書く必要のあるオプションがあり、これを真面目に考えるとさらに面倒になります。

% find ./hoge -L -regex ".*\.(h|cpp)"
find: unknown predicate `-L'

これらのオプションは0個以上で不定なので、引数の位置で判断するわけにいかないし、かといってパスを字面から判断するのもなかなか困難でしょう。

-D (デバッグ) と -Olevel (検査の最適化)は使わないと割り切り、-H -L -P(シンボリック関係のオプション)があったら-regextypeの前方に動かして、残りの引数の先頭が-で始まらない場合(=パス)をそれらと-regextypeの間に動かす(という挙動をするシェル関数なりスクリプトなりを書く)、あたりが手抜きの妥協点かなと思いました。

実際作ってみたら、こんな下らない事なのに意外と長く… → [Perl] GNU find wrapper to set -regextype.

2013年2月1日金曜日

Operaの怪しいショートカットを修正してやる!

# はてなダイアリーから移動した記事です。あまり真面目に整形していません。
  • Ctrl+kで検索しようとすると「アカウントを作成する必要があります」とポップアップが出る
  • Ctrl+Tabでタブを巡回しようとすると、2つのタブを往復する

ChromeやらFirefoxやらをメインに使っていると、この不要なオリジナリティにストレスがたまるため、AutoHotKeyになんとかしてもらいました。



ついでにCtrl+PageUp/Downも入れてみたけど、こっちは自分では使っていません。

検索については、Ctrl+eならば IE/Firefox/Chrome/Opera のデフォルト設定で検索が出来るので、そちらにシフトした方が良さそうですね。
Ctrl+Tabは、Operaだけ挙動が違うのでお仕置きが必要です。

ちなみにブラウザを複数使う理由は、SNSの類にログインするブラウザと、普段Webを巡回するブラウザを分けたいからです。Flashを使えば*1クロスブラウザで情報を取れるし、そもそもIPアドレスが同じなので大きな効果は期待できないものの、うっかりワンクリックで(ログイン状態の)SNSに何か投稿してしまうことは防げます。

*1:一応Local Shared Objectを消すアドオンを走らせてはいるけれど…