AndroidでPOCO C++ Librariesの実行方法
http://pocoproject.org/ ですが、1.4.2 から Android 対応しているのですが、マニュアルがドキュメント不足でいまいちわからなかったので、ここにメモしておきます。
ライブラリ自体のコンパイル方法
http://pocoproject.org/docs/99300-AndroidPlatformNotes.html どおりです。Ubuntu 12.04 (x64) でも MinGW でもどちらでもコンパイルできました。Ubuntu x64 の場合、aptitude install ia32 する必要があります。
こんな感じで、my-android-toolchain を作って、
export NDK=$HOME/android-ndk-r7c $NDK/build/tools/make-standalone-toolchain.sh --platform=android-8 --install-dir=$HOME/my-android-toolchain export PATH=$HOME/my-android-toolchain/bin:$PATH
こんな感じでコンパイルできます。
cd poco-1.4.3p1 ./configure --config=Android --no-samples --no-tests make -s -j4 make -s -j4 ANDROID_ABI=armeabi-v7a
そして、--platform=android-8 を --arch=x86 に変え、ANDROID_ABI=x86 にすると、x86 Android でも動作します。エミュレータで高速に動作するようになります。
ndk-build との併用方法
この部分がドキュメント不足でした。
まず、Application.mk に
APP_STL := gnustl_static
gnustl_static でも gnustl_shared でもどちらでも動作しますが、gnustl_shared の場合、Java 側から、System.loadLibrary("gnustl_shared"); する必要があります。
Android.mk に
LOCAL_CPP_FEATURES += exceptions rtti
を追加し、更に、
- LOCAL_CFLAGS には -Ipoco-1.4.3p1/Foundation/include -Ipoco-1.4.3p1/Net/include -Ipoco-1.4.3p1/Xml/include -Ipoco-1.4.3p1/Util/include を追加します。
- LOCAL_LDLIBS の先頭に、-Lpoco-1.4.3p1/lib/Android/armeabi-v7a -lPocoNet -lPocoXml -lPocoUtil -lPocoFoundation を追加します。
- LOCAL_STATIC_LIBRARIES に、libgnustl_static を追加します。
poco-1.4.3p1 へのパスは適切に変えてください。exceptions rtti は動作させるのに必須です。それ故、APP_STL は gnustl を使わないとダメです。
NativeActivity を使っているのですが、AndroidManifest.xml は例えば、こんな感じにします。
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.hoge" android:versionCode="1" android:versionName="1.0"> <uses-permission android:name="android.permission.INTERNET" /> <uses-sdk android:minSdkVersion="10" /> <application android:label="@string/app_name" android:hasCode="true" android:debuggable="true"> <activity android:name="android.app.NativeActivity" android:label="@string/app_name"> <meta-data android:name="android.app.lib_name" android:value="hoge" /> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
HTTP 通信とか、StringTokenizer とかがちゃんと動作するところまで確認しました。
ただし、POCO の Thread.start() が Android NDK r7c + POCO 1.4.3p1 の組み合わせでは正常に動作しませんでした。原因不明。自分で Pthread を使う分には問題無いです。
(追記)最初にこのブログを書いた際、大幅に間違いを含んでいたので色々修正しました。
SWT + JNA + Cairo
Win32 ではこんな感じで出来ます。Cairo は http://www.gtk.org/download/win32.php の all-in-one bundle から入手するのがおすすめ。
import com.sun.jna.Pointer; import org.eclipse.swt.internal.win32.OS; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.junit.Test; public class SWTTest { @Test public void test() { Display display = new Display(); Shell shell = new Shell(display); shell.setText("Shell"); shell.setSize(200, 200); shell.open(); int hWnd = shell.handle; int hdc = OS.GetDC(hWnd); try { Cairo cairo = Cairo.INSTANCE; Pointer surface = cairo.cairo_win32_surface_create(hdc); Pointer pattern = cairo.cairo_pattern_create_rgba(1, 0, 0, 0.1); Pointer cr = cairo.cairo_create(surface); cairo.cairo_set_source(cr, pattern); cairo.cairo_rectangle(cr, 0, 0, 100, 100); cairo.cairo_fill(cr); cairo.cairo_destroy(cr); cairo.cairo_pattern_destroy(pattern); cairo.cairo_surface_destroy(surface); } finally { OS.ReleaseDC(hWnd, hdc); } while (!shell.isDisposed()) { if (!display.readAndDispatch()) display.sleep(); } display.dispose(); } }
import com.sun.jna.Library; import com.sun.jna.Native; import com.sun.jna.Pointer; public interface Cairo extends Library { final Cairo INSTANCE = (Cairo) Native.loadLibrary("libcairo-2", Cairo.class); // cairo_t Pointer cairo_create(Pointer target); void cairo_destroy(Pointer cr); void cairo_set_source(Pointer cr, Pointer source); void cairo_fill(Pointer cr); void cairo_rectangle(Pointer cr, double x, double y, double width, double heigth); // pattern Pointer cairo_pattern_create_rgb(double red, double green, double blue); Pointer cairo_pattern_create_rgba(double red, double green, double blue, double alpha); void cairo_pattern_destroy(Pointer pattern); // Surface void cairo_surface_destroy(Pointer surface); // Win32 Pointer cairo_win32_surface_create(int hdc); }
クラウドのベンチマーク、GMOクラウドの利用可能ポート
UnixBench dhry2reg (整数演算)の結果
サーバー | dhry2reg |
---|---|
さくらのクラウド(1コア) | 2434.7 |
GMOクラウド(1コア KVM 深夜) | 3194.2 |
Core i5 ノートパソコン(2コア 2.4GHz) | 3216.5 |
新さくらのVPS (2コア 1GB) | 3607.1 |
Amazon EC2 m2.xlarge (2コア) | 4312.2 |
お名前.com VPS (3コア KVM) | 8712.0 |
さくらのクラウド(12コア) | 29735.7 |
GMOクラウド(12コア KVM 深夜) | 37111.2 |
Amazon EC2 cc2.8xlarge(16コア 32スレッド) | 38343.6 |
UnixBench 5.1.3 は最高16並列に制限されているので、Run の maxCopies を32に改変。
さくらのクラウドの数値は http://r2.ag/r612 より。中の人の計測。
新さくらのVPSは http://sakura.off-soft.net/blog/unixbench-new-sakura-vps.html より。Xeon E5645 2.40 GHzだそうです。お名前.com VPS は、おそらく Xeon X5675 3.06 GHz。
Flashの未来をFLASH MEETUPで聞いてきた!
先ほどまで、FLASH MEETUP http://atnd.org/events/22297 があり、Adobe Flash の現状・未来についての質疑応答のイベントがありました。Flash の技術の偉い方のちゃんとわかっている人が3名アメリカから来ていて、超内容が濃かったです!7〜9時の予定が11時まで延長して、京都から来た方は泊まりこみになりました!
Flash 関係で、最近誤解を招いてしまったことについて解説があったのですが、まぁ、ネットではたくさん出ているので、Flash の今後について話していたことについてこの記事では書きます。
あと、僕、間違ったことを書いていたらごめんなさい。私見も混じっています。アドビの太田禎一さん @otachan さんに聞くと色々と教えてくださると思います。
全体の方針
現状、Flash がよく使われているのは、「ゲーム」「動画」「広告」なんですが、ゲームと動画に今後は注力していくとしていました。
Stage 3D
Flash Player 11.0 から入った GPU を呼び出せる Stage 3D ですが、方針としては、
- 2D フレームワーク や 3D フレームワーク経由で使ってね。
- Adobe 自前ではこれらのフレームワークを作ることはなく、その下のレイヤーだけに注力する。
- 3D のオーサリングツールも作らない。Flare3D のオーサリングツールを紹介していました。
あと比較的高度な話として、
- 11.0 では Pixel Bender 3D で for ループが出来なかったり、描画命令もすごく種類が少ないのは、広範にいろいろなコンピュータでテストしてみたところ、あまりにもちゃんと動いてくれない GPU が多すぎて、その結果、こういう命令になった。GPU ベンダーにバグ修正の要望を色々出している。
- バグのある GPU は動作させないブラックリストを Flash Player は持っていて、統計的に 50% 近く弾いている。そのリストは今後公開予定。最新のドライバなら動く GPU でも、ドライバのバージョンが古かったりするとブラックリスト入りしている場合がある。最初のインキュベータ版では「2009年1月よりも前にリリースされたドライバ」を全て弾いていたそうです。
- それでも、WebGL のブラックリストよりは広範囲のドライバをサポートしている。(例えば、WebGL の場合、第1世代 Core i の Intel HD Graphics ですらブラックリストに入っています)
モバイル関係としては、
HTML 5 向けのアニメーションツール
Adobe Edge で HTML 5 向けの2Dアニメーションオーサリングツールを公開していますが、スマートフォンが HTML 5 しか使えなくなった以上、これは積極的に投資してく方針みたいです。CS6 -> CS7 とどんどんこの手の機能を良くしてく感じみたいです。話の流れだと、Adobe 製のアニメーションツールで
なんか、話の感じだと、ActionScript 3 → JavaScript のコンパイラも研究している感じでした。本当か?
ここらへんの話は特にデモがなく、詳細は不明です。
プロファイリングツール
Flash の新しいプロファインリグツール(ボトルネックを探すツール)のデモもやりました。フレームごとに、どの処理・スクリプトに何msかかったか見ることができる GUI ツールです。良い感じでしたよ!スマートフォン相手にも Wifi 経由でリモートプロファイリングができるそうです。
サイレントアップデート
Flash Player 11.2 からサイレントアップデートの機能が入り、ユーザーが拒否しない限り、Google Chrome みたく、勝手に自動的にアップデートするようになりました。これを、Mac OS X にも近いうちに入れる予定だそうです。(Liunx は yum や apt などに頼るのでしょう)
サウンド
現状200〜250ms 程度サウンドのレイテンシがあるそうですが、それを 40ms 程度まで短縮した Flash Player を今後出すそうです。
国際化
これは会場の質問から出たのですが、Flash が日本語など非英語圏でテストが甘くバグが多い、という文句が出たのですが、(日本語入力がテキストフィールドでできなくなったり、マイク選択で英語以外のデバイス名が含んでいると動作がおかしくなるなど)、「頑張ります」的な回答しかなかったのですが、日本語でバグレポートを出来る場を作って欲しいと言われていて、これはそのとおりだと思います。
Alchemy 2
C/C++ ライブラリを Flash Player 内で動かす Alchemy ですが、一度死にかかった感じがあるのですが、Alchemy 2 としてちゃんと再生させることが発表されています。(技術的に何が変わるのか質問したかったのですが、タイムオーバーで質問出来なかった)。話によると、ネイティブと変わらないパフォーマンスで動いているよと言っていました。コンパイラは LLVM のコンパイラなので、最適化関係は LLVM の強力な最適化で行われるのですが、あとは、生成される命令がどの程度ちゃんと JIT されるかなんですが、まぁ、期待!
ネイティブエクステンションという選択肢も Adobe AIR ではありますが、
という使い分け方を推奨していました。
mixiアプリのユーザーIDプラットフォーム共通化の移行方法
mixiが海外のSNSとプラットフォーム共通化をするらしく、その関係で、今まで数字のIDだったのが、文字列のIDに切り替わります。その関係で、mixiアプリ提供者は今月中(2011年10月)に新方式に移行が必要です。
http://developer.mixi.co.jp/news/news_apps/009668.html
なんか、あまり手法とかブログで見かけなかったので、やり方とか書いておきます。手抜きしたい方の参考にどうぞ。
まず、変わるのは、ID だけで、API は変わりません。今まで、ID を文字列で管理していた人は、データベースの ID さえ、差し替えてしまえば対応完了です。数値でやっていた人は、文字列にプログラムを書き換える必要があります。
一連の話、テストアプリで一通り練習してから、本番アプリで行ってくださいね。
ステップ1
http://developer.mixi.co.jp/appli/com/change/setting/trans_id/ にあるように、ID変換API の申請をします。アプリが稼働中の状態でやってしまっても、通常は大丈夫です。
ステップ2
まず、旧ID の一覧が必要です。in.csv は(1列のCSV、つまりカンマなし)で旧IDをずらずらと並べた形式にしました。
in.csv の作り方は、アプリ次第ですが、僕の場合は、PostgreSQL でこんな感じでした。
COPY (SELECT mixi_id FROM account_mixi) TO '/tmp/in.csv' CSV;
ステップ3
次は、旧ID → 新ID の変換です。RESTful API を使うと、変換表が手に入ります。こんな感じの Java のアプリでやりました。http://code.google.com/p/opensocial-java-client/ が必要です。
java -classpath .;opensocial-1.0.jar;commons-codec-1.3.jar;json_simple-1.1.jar;oauth-20090825.jar MixiOldIdConverter in.csv out.csv failed.csv
で実行します。一度実行したら、out.csv や failed.csv に保管するので、2回目は差分だけ実行できます。1回目は、アプリが動いた状況で実行し、その後必要なら、数回、アプリが実行している状態で行い、最後にアプリを停止して変換すると、アプリの停止時間を小さく出来ます。
import org.opensocial.Client; import org.opensocial.Request; import org.opensocial.RequestException; import org.opensocial.Response; import org.opensocial.auth.OAuth2LeggedScheme; import org.opensocial.models.Model; import org.opensocial.services.PeopleService; import java.io.*; import java.util.Date; import java.util.HashSet; public class MixiOldIdConverter { // 本番 private static final String consumerKey = "fuga"; private static final String consumerSecret = "barbar"; // テスト // private static final String consumerKey = "fugaTest"; // private static final String consumerSecret = "barTest"; public static void main(String[] args) throws IOException { File inFile = new File(args[0]); File outFile = new File(args[1]); File failedFile = new File(args[2]); HashSet<String> converted = new HashSet<String>(); readOutFile(outFile, converted); readOutFile(failedFile, converted); BufferedReader reader = new BufferedReader(new FileReader(inFile)); PrintWriter writer = new PrintWriter(new FileWriter(outFile, true)); PrintWriter failedWriter = new PrintWriter(new FileWriter(failedFile, true)); int lineNo = 0; String line; while((line = reader.readLine()) != null) { if (line.length() == 0) continue; if (converted.contains(line)) continue; lineNo++; try { String platformUserId = convert(line); writer.println(line + "," + platformUserId); } catch (Exception e) { //e.printStackTrace(); // ここコメントアウトしてもあまり問題ない failedWriter.println(line); } if ((lineNo % 10) == 0) System.out.println(lineNo + " " + new Date()); } failedWriter.close(); writer.close(); reader.close(); } private static void readOutFile(File outFile, HashSet<String> converted) throws IOException { if (outFile.exists()) { BufferedReader reader = new BufferedReader(new FileReader(outFile)); String line; while((line = reader.readLine()) != null) { if (line.length() == 0) continue; converted.add(line.split(",")[0]); } reader.close(); } } public static String convert(String oldId) throws IOException, RequestException { OAuth2LeggedScheme authScheme = new OAuth2LeggedScheme(consumerKey, consumerSecret, oldId); Client client = new Client(new MixiProvider(), authScheme); Request viewer = PeopleService.getViewer(); viewer.addParameter("fields", "platformUserId"); Response response = client.send(viewer); Model person = response.getEntry(); return (String) person.getField("platformUserId"); } }
import org.opensocial.providers.Provider; public class MixiProvider extends Provider { public MixiProvider(){ super(); setName("mixi"); setVersion("0.8"); setSignBodyHash(false); setRestEndpoint("http://api.mixi-platform.com/os/0.8/"); } }
ステップ4
- Webアプリを停止する。
- データベースのバックアップをとる。
- in.csv の最終形を作る。
- 変換して、out.csv の最終形を作る。
- この後記載する SQL みたいな感じで、新 ID に置き換える。
- 念のため、別なファイル名で、再度、データベースのバックアップをとる。
- 「IDのプラットフォーム共通化対応完了」をクリック。これ以降、新 ID で mixi の方からは応答が来るようになります。
- Webアプリを再開する。
CREATE TABLE old_new_mixi_id_map ( old_mixi_id VARCHAR(255) PRIMARY KEY, new_mixi_id VARCHAR(255) NOT NULL ); COPY old_new_mixi_id_map FROM '/tmp/out.csv' CSV; UPDATE account_mixi SET mixi_id = (SELECT new_mixi_id FROM old_new_mixi_id_map WHERE old_new_mixi_id_map.old_mixi_id = account_mixi.mixi_id) WHERE mixi_id in (SELECT old_mixi_id FROM old_new_mixi_id_map);
場合によっては、他にも関連するテーブルの情報を削除する場合がアプリによってはあると思います。(僕の場合は、他に2カ所、データを削除しました)
福島県飯舘村は屋内退避させるべきか否か
ソフトバンクの孫正義さんが、Twitterで、政府の出している避難指示に関して、http://twitter.com/masason/status/51832607117295616 以下のように書いていて、この問題についてです。
政府は飯舘村や南相馬市に明確な避難命令を出すべき。RT @mryoshi55: 政府が中途半端なことをするから、ここ米沢の避難所から飯館村や南相馬市に戻る避難者が今日出てきた、今はまだ止めた方が良いと思う
http://twitter.com/masason/status/51836389716795392
「直ちに問題無し」「避難命令拡大不要」を連呼する政治家や学者は自らの家族がそこにいても避難させないのだろうか? @dunce_jp @masason: 政府は飯舘村や南相馬市に明確な避難命令を出すべき。
僕は、政治哲学として、「平時に決めた緊急時マニュアルはちゃんと守るべき」というのが僕のスタンスです。国が決めた、ルールは以下の通りです。
対策 | 外部被ばく | 内部被ばく |
---|---|---|
屋内退避 | 10ミリシーベルト〜50ミリシーベルト | 100ミリシーベルト〜500ミリシーベルト |
避難 | 50ミリシーベルト以上 | 500ミリシーベルト以上 |
この問題、色々な単位が飛び交っていて、ややこしいのですが、これは「累積量」です。混乱している方もいますが、「1時間あたりの」というやつではないです。なお、1ミリシーベルト以下なら、日常で自然から浴びるレベルなので無視できるとされています。そして、健康被害が出るのは500ミリシーベルトといわれ、福島第一原発で命がけで作業に当たっている人たちで100ミリシーベルト以上被ばくしている人が多数いますが、今のところ大丈夫みたいです。国の基準の詳細は http://www.mext.go.jp/component/a_menu/other/detail/__icsFiles/afieldfile/2011/03/28/1304305_2810.pdf の末尾2ページをご覧ください。
現在は、
- 半径20km以内 - 避難
- 半径20〜30km以内 - 自主避難(元は屋内退避)
という指示が出ています。
あと、内部・外部とあるのですが、以下、「外部被ばく」の方で、計算します。なお、「内部被ばく」の方は、SPEEDIによるコンピューターによる概算の予測値があるのですが、外部被ばくの方は17日以降は実測値があり、より実際に近いはずなので、外部被ばくの方をみます。この違いも、ややこしいよね。
なお、僕はIT業界の人で、原子力は素人ですが、一連の話、超ひも理論(素粒子)を研究している友人に色々教えてもらいました。(ただし、彼も、厳密には原子力工学は専門じゃないです)。色々ありがとうね!あと、専門家の皆様、この記事に誤りを含んでいたら、訂正お願いいたします。m(_ _)m
次に、外部被ばくで問題となる、飛んでくる放射性物質ですが、風に流されて飛んできて、雨が降ると大量に地面に落ちてきて、地面に降りてくるとあまり動かなくなり、その場で放射線をまき散らすそうです。放射線には半減期というのがあり、例えば、今回、大量にばらまかれている、ヨウ素131だと、半減期が8日なので放射線の量は8日で1/2、16日で1/4とだんだん減っていきます。
そして、放射性物質が大量に飛散した原因は、3月15日あたりに、福島第一原発のバッテリーが切れた後、原子炉の格納容器内の圧力が高まったので、中の空気をそのまま外に逃がす作業を緊急的にやっていました。ここら辺の経緯は 福島第一原子力発電所事故 - Wikipedia をどうぞ。
ただし、この作業は、最近は行っていません。なので、
ならば、あとは半減期で減っていくだけです。確証はもちろんないですが、現状の様子だと、この2つ、どっちも起きる可能性は低そうな気がします。(ちなみに、最近問題になっているのは、空気中ではなく、海に放射性物質をまき散らしています)
というわけで、新たに放射性物質が増えないなら、半減期を足し算(積分)すれば、放射線量の「累積量」がわかります。
その計算に必要なデータは文部科学省が http://www.mext.go.jp/a_menu/saigaijohou/syousai/1304001.htm で公開しています。風は北西方向に吹くことが多く、北西方向に多く放射性物質が飛んでしまったので、北西方向の以下の3地点を選びました。全て、30kmエリアの外です。自主避難などが出ていないOKとされている場所です。
場所 | 距離 | 計測地点番号 |
---|---|---|
浪江町津島 | 30km | 32 |
飯舘村 | 40km | 62 |
福島市 | 60km | 1 |
文部科学省が計測しているのは、役場や小学校があるなど、それぞれの集落の中心部です。今問題になっているのが「飯舘村」です。「浪江町津島」は自主避難してしまったのか、多くの人が残っているのか僕はよくわかりません。
結論
先に結論を書いてしまうと、以下の通りです。mSvはミリシーベルトです。
場所 | 距離 | 15日から積分 | 17日から積分 | 判定 |
---|---|---|---|---|
浪江町津島 | 30km | 39.4mSv | 30.4mSv | たぶんアウト |
飯舘村 | 40km | 8.3mSv | 6.5mSv | たぶんギリギリセーフ |
福島市 | 60km | 2.1mSv | 1.7mSv | たぶんセーフ |
計算方法
まず、文部科学省が発表している元データです。15日から飛散しているのですが、多くの地点で計測を始めたのは17日からなので、17日からのデータです。単位はマイクロシーベルト/時です。1000マイクロ=1ミリです。
日付 | 経過日数 | 浪江町津島 | 飯舘村 | 福島市 |
---|---|---|---|---|
3月17日 | 0 | 170 | 7 | |
3月18日 | 1 | 150 | 30 | 8.5 |
3月19日 | 2 | 136 | 26.5 | 7.2 |
3月20日 | 3 | 110 | 25.8 | 5 |
3月21日 | 4 | 90 | 20.4 | 5 |
3月22日 | 5 | 75 | 15.3 | 3.5 |
3月23日 | 6 | 75 | 16.8 | 4 |
3月24日 | 7 | 65 | 13.2 | 3.6 |
3月25日 | 8 | 65 | 12.3 | |
3月26日 | 9 | 46 | 10.2 | 2.5 |
3月27日 | 10 | 50 | 11.2 | 3.5 |
飯舘村の3/17のデータはおかしかったので空欄にしました。3/18のデータも30以上となっていますが、30としました。
これをグラフにプロットすると以下のようになります。半減期は指数関数で表現できるので、Excelの近似曲線は「指数近似」です。浪江町津島や飯舘村はかなり綺麗に近似曲線にフィットします。福島市は少し不正確です。
この近似曲線を積分すると、累積量がわかるのですが、3月15日は経過日数「-2」なので、「-2〜無限大」で積分すると累積量がわかります。ただし、3/15や3/16のデータがない部分をこのように予測値で埋めて良いのかどうかは、若干、不確実です。しかし、それにより、判定結果が変わるわけではないので、この手法を採用しても大丈夫だと思います。「結論」の「15日から積分」が「-2〜無限大」で「17日から積分」が「0〜無限大」です。
積分計算は WolframAlphaを使いました。計算結果のリンクは以下の通り。浪江町津島の分だけ、キャプチャ画像を張ります。
- http://www.wolframalpha.com/input/?i=%28integrate+164.5exp%28-0.13x%29+dx+from+-2+to+infinity%29+24
- http://www.wolframalpha.com/input/?i=%28integrate+33.596exp%28-0.124x%29+dx+from+-2+to+infinity%29+24
- http://www.wolframalpha.com/input/?i=%28integrate+7.6315exp%28-0.1054x%29+dx+from+-2+to+infinity%29+24