ラベル プログラミング の投稿を表示しています。 すべての投稿を表示
ラベル プログラミング の投稿を表示しています。 すべての投稿を表示

2018年7月30日月曜日

bloggerで特定ラベルの投稿一覧を出す version 2

自分の以前のブログ記事「bloggerで特定ラベルの投稿一覧を出す」で方法を紹介して、このブログでもそれを使ってました。
それを見て、私のscriptを使ってくださる方もいらっしゃるようで、あるヘビーなブロガーの方に、ひとつのラベルに記事がたくさんあると全部表示されない、と教えていただいた。
調べてみると、150本以上記事のあるラベルを表示させようとすると、それ以上表示できない様子。
たくさん記事をアップしないと発見できない現象で、うちのブログは、記事数が少ないので発見できていなかった。
blogger APIでとれるfeedの最大数が原因だったんですけど、ただ、もともと最大150だったわけではなく、元々500だったのが2015年の末頃に減らされたらしいとのこと。

今見たら、私の元記事は、2012年でした。結構前なのね・・・
というわけで、いい機会なので同一ラベル記事150本超の場合にも対応して、version 2にしたので、記事をアップしました。

使い方は、Blogger の管理画面「ページ」から新しいページを作りhtml編集モードにして

<div id="entry_list_by_label"><script src="https://cdn.rawgit.com/choniwaniwani/wasure/92f7a895/toc/bloggerFeeds.2.js"></script>
<script>load_entry_list("ラベル名称");</script></div>
を貼り付けて、ラベル名称を書き換えるだけです。
こんな感じの同一ラベル記事をまとめたページを作成します。

ラベル名称は、そのまんまラベルの名前です。日本語でもOKでした。
で、このタグ貼付部分より前や後に普通に文章入れてもOKです。

タグ内部に入れてもいいので、レイアウトは多少カスタマイズできます。リンクのaタグには'linkHref'という名前の未使用classも入っているので、cssでカスタマイズも可。


以下、javascriptのコードに興味ある方向けの内容です。

なお、codeは、githubにおいてありますので、javascriptいじれる方は、勝手にコピって改造して使ってもOKです。
コード内で、feedを呼ぶところは、これなんだろうという感じですが、詳しいパラメータの解説は、こちらにあります。
ただし、この中には、bloggerでは使えないパラメータもあります。(やってみないとわからない。)

あと、今回bloggerのhtml編集画面の変な仕様というかバグを見つけたのですが、bloggerは、全角の記号をすべて勝手にescapeしてしまうようです。 それなので、たとえば、javascriptの文字列の中でも・(中黒)があると&#12539;になってしまいます。
全角なんだからほっといてほしいですほんとに。それで、最初ラベル名に中黒が入っていると動かないという謎の現象が発生していました。

2017年11月9日木曜日

javascriptで簡単なカリー化関数を作った(ES6版)

最近、scalaからjavascriptに不本意ながら引っ越してきました。初めは嫌々ながらだったんですけど、ES6になってめっちゃ書きやすくなってるんですね。知りませんでした。
そんなわけで今回は、カリー化の仕組みがjavascriptの標準になさそうだったので、簡単にカリー化したいと思って調べてみると。 結構良さそうなのが、ありました。(Qiita: JavaScript でカリー化)
そのまま使っても良かったんですけど、僕はjavascriptでは、できるだけthisを使わないようにしているので、リンクの記事のcontextがいらないのと、その場合の空の括弧()がいらないので、上の記事のコードを参考に改造しました。
あと、他の言語から来ると、関数宣言の括弧の中にない引数をargumentsを使って取るのは気持ち悪いので、ES6の可変長引数を使ってこんな風にしてみました。
Function.prototype.curry = function (...args) {
  let func = this;
  function partial(...args) {
    return (args.length >= func.length)
      ? func.apply(null, args)
      : function(...ret_args) {
          return partial.apply(null, [...args, ...ret_args]);
        }
  }
  return partial.apply(this, args);
};
とりあえず、こんな感じにして動作確認
function sum1(a, b, c) {
  return a + b + c;
}
let sum2 = ((a, b, c) => a + b + c).curry()

console.log(sum1.curry(4, 5, 6))  // <- 6
console.log(sum1.curry(4)(5)(6))  // <- 15
console.log(sum2(10)(11)(12))  // <- 33
これでいいんだけど、あまりビルトインのprototypeを勝手に拡張すんな!としつこくMDN(ココやココ)に書いてあるので、僕は潔癖でないのでそういうの嫌なんだけど、まあ後でcurryメソッドとか正式に追加されたらそれはそれで嫌なので、ただの関数版も作ってみた。
scalaのimplicit conversionが懐かしいぜ・・・
function curry(fn) {
  return function partial(...args) {
    return (args.length >= fn.length)
      ? fn.apply(null, args)
      : function(...ret_args) {
          return partial.apply(null, [...args, ...ret_args]);
        }
  }
};
こっちの使い方はこんな感じ
let sum3 = curry((a, b, c) => a + b + c)

// sum1は、上のを使いまわし
console.log(curry(sum1)(4, 5)(6))  // <- 15
console.log(curry(sum1)(1)(2)(3))  // <- 6
console.log(sum3(20)(21)(22))  // <- 63
console.log(sum3(2)(4, 6))  // <- 12
まあ、難しいこと考えなければこれで良いような気がします。
関数版は、憎たらしいthisも使わないですんでるし。
昔、10年くらい前には、
{javascriptって何でもfunctionで出来てて意味わかんねー} 
とかって思ってたんすけど、その基本設計と最近のES5,ES6と続く言語の拡張により俄然、モダンな書き方ができる言語に変化してきてるんですね。

2017年1月18日水曜日

c++で、scala風ifをやりたい

scalaをしばらくやっていると、c++を書いた時にifが値を返さないのでトサカにくることがある。

三項演算子とラムダ式を使えばもちろんできるんだけど、超絶汚くなる。けど、マクロにしたら案外すっきりしたので、記事アップ。
// scala風if
#define IF(COND) (COND)?[&](){
#define ELSE ;}():[&](){
#define ENDIF ;}()
#define IFRES return
こんな感じ。c++11以降ね。使うときは、
// scala風if sample1
    const int i = 5;
    const auto s = IF(i == 4) {
        cout << "case true" << endl;
        IFRES "if true!";
    } ELSE {
        cout << "case false" << endl;
        IFRES "if false!";
    } ENDIF;

    cout << s << endl;
そこそこ見やすい。ENDIFが必要なのは勘弁してね。
c++は、中括弧の最後の値が中括弧全体の値にならないので、IFの戻り値にしたい値にIFRESを付けてね。
IFRESは、ただのreturnなんだけど、直にreturnって書くと関数全体のreturnに見えてしまい、わけわからなくなるので、このキーワードを使います。
逆に言うと、IFやELSEの中から関数の外へ直接return出来ないので、あしからず。returnしたい人は、別にifの戻り値が欲しいわけじゃないので普通のifを使ってください。

あと、ENDIFマクロの最後にセミコロンをあえて含めずに、使うときにセミコロンをつけるようにしたのは、コンストラクタの初期化子でも使いやすくしたかったから。

IFとかELSEの後がブロックでなくてもOK。
// scala風if sample2
    const int i = 5;
    const auto s = IF(i == 4) IFRES "if true!"
                   ELSE IFRES "if false!"
                   ENDIF;
    cout << s << endl;

2016年10月20日木曜日

opencv2系をgcc6でコンパイルしたらエラーになった

opencv2.4.13をubuntu16.10環境(gcc6)でコンパイルしたらこんなエラーが出て止まった。
In file included from /usr/include/c++/6/bits/stl_algo.h:59:0,
                 from /usr/include/c++/6/algorithm:62,
                 from /opencv-3.1.0/modules/core/include/opencv2/core/base.hpp:53,
                 from /opencv-3.1.0/modules/core/include/opencv2/core.hpp:54,
                 from /opencv-3.1.0/modules/core/include/opencv2/core/utility.hpp:52,
                 from /opencv-3.1.0/build/modules/core/precomp.hpp:49:
/usr/include/c++/6/cstdlib:75:25: fatal error: stdlib.h: そのようなファイルやディレクトリはありません
 #include_next <stdlib.h>
{stdlib.hがありませんって、そんなわけねーだろ!}
一瞬、あせったけど、cmakeで
-D ENABLE_PRECOMPILED_HEADERS=OFF
付けとけば、とりあえずOKっぽい。
opencvの方がおいおいgcc6対応すると思うけど、今のところこれで切り抜けられそうです。

2016年4月26日火曜日

Django (1.9) で、PyMySqlのDictCursorを使う方法。

対象

Djangoから、DBに接続してデータをごにょごにょやりたいんだけど、ORMが嫌いで
「Viva! SQL」 な人。

やりたいこと

Djangoのconnectionsを使うと、SELECT文の結果カーソルがtupleになってしまいフィールド順序でのアクセスになってしまうので、こんな風に
{'name': 'Taro Yamada', 'age': 25}
Dictionaryで結果がほしい。

やったこと (簡潔編)

ORM使わないなら、Djangoのconnectionsいらないから、自分でconnectする。
参考URL: YoheiM.NET

やったこと (だらだら編)

Djangoで、settings.pyにDBを以下のusersのように追加して、(docs.djangoproject.jpより引用)
DATABASES = {
    'default': {
        'NAME': 'app_data',
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'USER': 'postgres_user',
        'PASSWORD': 's3krit'
    },
    'users': {
        'NAME': 'user_data',
        'ENGINE': 'django.db.backends.mysql',
        'USER': 'mysql_user',
        'PASSWORD': 'priv4te'
    }
}
で、データがほしいところで
from django.db import connections

conn = connections["users"]
cur = conn.cursor()
cur.execute("SELECT * FROM persons WHERE id = %s", 100)
row = cur.fetchone()
print(row)
てな感じで、書くとprintされるのが、以下みたいな感じ
(100, "Taro Yamada", 25, 1, True)
{えーっ。tupleですかー? これじゃ、templateにrowを渡した時に、{{ row.1 }} な感じで読み取らないといけないから、わけわかめじゃんよー・・・。俺は、class Person を作りたくないんだってば }
どうやら調べると、DictCursorなるものを使えば、rowがtupleでなく
{'id': 100, 'name': 'Taro Yamada', 'age': 25, 以下略}
のようにdictionaryで取れるらしい。(参照: stackoverflow) 押忍。じゃあ、そこに
connection.cursor(pymysql.cursors.DictCursor)
なんて記述が、あったからさっきの上のコードをこんなふうに変更してみたところ
--- cur = con.cursor()
+++ cur = con.cursor(pymysql.cursors.DictCursor)
こんなエラーが
    cur = connections['users'].cursor(pymysql.cursors.DictCursor)
TypeError: cursor() takes 1 positional argument but 2 were given
{むきーっ!! }
どうやら、connections[‘users’]でとれるconnectionと、上記stackoverflowサンプルのconnectionは、別物らしい。
そりゃそうじゃよな。
具体的には、前者が ‘django.db.backends.mysql.base.DatabaseWrapper’
で、後者が ‘pymysql.connections.Connection’
さらに調べると、別のstackoverflowで、
「djangoに、DictCursorなんて、なぁぃですね~↑」(No there is no such support for DictCursor in django.)
{なにーっ!! }
さらに、その回答の解決案がびみょ~~な感じ。
でも、考えてみるとDictCursorを使いたいって時点で、djangoのORM無視してSQL投げたいってことなんだから、自分でconnectすればいいじゃんか。 ← 早く気がつけ。
幸い、親切な人が素晴らしい解説を書いている(YoheiM.NET)ように、使い方は簡単。
ただ、DB接続設定は、settings.pyに残しておきたいのと、データを使う側でのコードを簡潔にしたいので、最終的に以下のようになった。
まず、settings.py に、connectionまで定義してしまってアプリ全体で使い回す。
import pymysql.cursors

USERS_DB = pymysql.connect(
    host='localhost',
    user='db_user',
    password='db_pass',
    db='users',
    charset='utf8',
    cursorclass=pymysql.cursors.DictCursor)
最後の一行が、ポイント。 settings.pyってpythonファイルだから、こんなものも置けるんだ・・・
DBにアクセスしたい方では、
from django.conf import settings

conn = settings.USERS_DB  # ←これ便利
cur = con.cursor()
cur.execute("SELECT * FROM persons WHERE id = %s", 100)
row = cur.fetchone()
print(row)
これで、 {'id': 100, 'name': 'Taro Yamada', 'age': 25, 以下略} が、めでたくprintされる。
ついでに書くと、templateに渡すところでは、↑のrowを利用して、views.py で
render(request, 'users.html', {'person': row})
なふうに、簡単に渡して、template側では、
{{ person.name }}
とか
{{ person.age }}
みたいに、見てすぐにわかるように呼び出せるようになった。

でも、django.db.backends.mysql.base.DatabaseWrapperと pymysql.connections.Connectionのようにオブジェクト自体が異なっていても、executeの書き方やfetchoneで呼ぶところなど、共通だからほとんどコード変更の必要が無いのって、pythonからのDBアクセス方法がPEP 249で規定されてるからなんだよね。
pythonって文法が好きになれないんだけど(俺が好きなのはscala)、取り巻く環境がいろいろと整ってるから結局使っちゃうのよ。

長いところ、最後までお読みいただきありがとうございました。

2015年10月8日木曜日

gflagsとglog(Google logging)を windows 用にVisualStudio2015でビルドした

ググっても出てこなかった(or古い情報で使えなかった)ので、メモ。
当方の環境はvs2015, windows10

cmake

とにかくcmakeが必要。 入っていない場合は、ココから入れる。

glog

github から落とすと(2015-10-08 時点) 、google-glog.sln がいるがこいつがくせ者。vs2015で開くときにconvertしてもビルド時に失敗する。
なので、付属のslnは使わずにcmakeで作りましょう。

gflags

こいつも同じ。github にあるChangeLog.txt に 「Renamed google-gflags.sln to gflags.sln」なんて記述があったから、一生懸命探してしまったがそんなファイルはない。
なので、cmakeでslnを作って下さい。

2015年3月2日月曜日

eclipse使ってて、突然gitのcommitができなくなった

状況

eclipse(Luna)使ってるんだけど、ある日突然、gitのcommitができなくなった。
commitしようとすると、

'committing changes' has encountered a problem.
An internal error occurred

なんてエラーがダイアログBoxに出て、commitできない。そのDialog Boxに付いている”Details”ボタンを押しても

An internal error occurred
Exception caught during execution of commit command

しか書いてなくて、わけわからなかった。

ネットで調べたら、ここ に書いてある方法で解決したんだけど、下の方にちょこっと書いてあって見つけにくかったのでメモを残します。

解決法

.gitの中にある、 index.lock を削除する。

自分のケースでは、これだけであっさり解決しました。

2014年10月25日土曜日

漢字プリント 簡易作成ページ

漢字の練習をしたいとき(させたいとき)に一度間違えた漢字だけを集めて練習をしたいようなときがある。
そんなときに、間違えた問題だけを集めたプリントがあると便利なのだが、自分で作るとなると形を整えるのが結構面倒。

てなわけで、間違えた問題をテキストで取っておいて貼り付けるとそこそこ整形するようなものを作ってみました。
印刷用画面生成ボタンを押して表示された画面をブラウザの印刷機能で印刷してください。A4縦だと収まりがいいです。
動作確認は、chrome,safariで行っています。詳しい使い方は、ボタンの下を見てね。

  

各行に漢字の問題を
  漢字の(問題,もんだい)を作る。
のように書きます。実際は、ここで書くのではなく、どこかのテキストファイルにでもまとめておきます。
()の中はカンマ区切りで前半が正解の漢字、後半に読みがなを入れておきます。
送り仮名まで問題にしたいときは、上の例の3行目のように送り仮名まで含めて書いてください。

また、問題文の難しい文字に読みがなを付けたいときは、上の例の2行目のように
  (*真相,しんそう)を(究明,きゅうめい)する。
漢字の前に*を付けてください。このように指定すると問題ではなくただのふりがなとして作成します。

このページを作成するにあたって、freefielderさんの縦書きhtml作成用javascript(h2v.js)を使用しました。すごく便利なscriptです。ありがとうございました。

2014年7月3日木曜日

PlayFramework 2.3.1 with Scala 2.11.1 へプロジェクトをアップグレードした時のメモ

最近、ScalaもPlayもいろいろアップデートしていて速くなったとか(Scala)、速くなったとか(Play)言っているから、
{まあ、入れてみるか}
とやってみたら、以前のプロジェクト(Play2.2.x with Scala2.10.x)をアップグレードしようとした時いろいろややこしかったので、別のプロジェクトをやるときに絶対忘れそうなのでメモっておく。

まず、新しいPlayとScalaを公式ページでdownloadしようとすると、activatorなるものをインストールするように誘導された。
{activatorってなんじゃい}
完全に浦島太郎状態。どうやら、Scala, Play, Akkaやらサンプルやらwebエディターやらwebデバッガーやらセットになっていて、これ入れれば全部OKみたいなものらしい。
しかもplayコマンドとかsbtコマンドとか、全部 activator コマンドでやれということらしい。
で、activatorインストール後、今までのPlayのprojectフォルダに行って、
activator compile
とかいきなりやったけど、エラーの山。
{ま、そりゃそうだよな。しかたないか。}
なので、projectのファイルを色々変更した。

まず、project/plugin.sbt のplayのバージョンを以下のように変更
addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.1")
次に、project/build.propertiesのsbtバージョンを以下のように変更
sbt.version=0.13.5
そんで、project/Build.scalaをこのサイトのSbt sampleを参考にこんな感じ変えてみた。
import sbt._
import Keys._

object ApplicationBuild extends Build {

  val appName         = "xxxxx"
  val appVersion      = "1.0-SNAPSHOT"

  val main = Project(appName, file(".")).enablePlugins(play.PlayScala).settings(
    version := appVersion,
    scalaVersion := "2.11.1",
    libraryDependencies := {
   CrossVersion.partialVersion(scalaVersion.value) match {
     // if scala 2.11+ is used, add dependency on scala-xml module
     case Some((2, scalaMajor)) if scalaMajor >= 11 =>
       libraryDependencies.value ++ Seq(
         "org.scala-lang.modules" %% "scala-xml" % "1.0.1",
         "org.scala-lang.modules" %% "scala-parser-combinators" % "1.0.1",
         "org.scala-lang.modules" %% "scala-swing" % "1.0.1",
         "com.github.scala-incubator.io" %% "scala-io-file" % "0.4.3-1")
     case _ =>
       // or just libraryDependencies.value if you don't depend on scala-swing
       libraryDependencies.value :+ "org.scala-lang" % "scala-swing" % scalaVersion.value
   }
 },   
 scalacOptions += "-feature"
  )

}
参考ページのコードに追加したのは、scalaxのscala-io-fileの部分、モジュール名とかバージョンとかわからなかったけど、MVNRepositorysというサイトから持ってきた。このサイトは知らなかったけど、こういうときはメチャメチャ便利なところ。

これでとりあえず動くようになった。

2014年4月11日金曜日

[scala][akka] microkernelを使って独立したプロセスに立てたRemote Actorとの通信サンプル

自分は、akkaの「Let it crash」というという発想が大好きなんです。
初めて「Let it crash」というスローガンを見たとき
{だよね。それでいいんだよね。}
と感激しました。

ただ、crashさせるためのSupervisor(doc、サンプル)の仕組みは、Actorはcrashさせるけど、jvmまでは殺してくれない。自分の場合、ヘビーな計算をscalaからloadLibraryしたc++のモジュールをJNA経由で使ってやっているので、jvmごとcrashさせたいんです。(外部libraryのunloadはできないようなので・・・)

そこで、登場するのがakkaのmicrokernelで、こいつを使うと簡単に独立したプロセスのjvmでActorを立てることが出来る。
必要に時は、こいつをjvmごとkillして復活させればいい ← もっとスマートな仕組みがきっとある気がする

で、HelloWorldのサンプルを書いてみた。
listenポートを可変にしたかったので、confファイルを使わない形で作ってみた。
application.confとかに設定が分かれてないほうがサンプルとしてもわかりやすいし。
まず、リモートで接続される側のmicrokernel
パラメータは、起動時に引数として渡せないので、起動する時は、
env AKKA_PORT=12345 akka hello.world.Sample.HelloLauncher
て感じで、環境変数経由にする。
あと、実行時にクラスが見つかんないみたいに怒られた時は、とりあえずjarに固めて、akkaのdeployフォルダに置けば見つかるようになります。
package hello.world.Sample

import akka.actor.{ Actor, ActorSystem, Props }
import akka.kernel.Bootable

class HelloLauncher extends Bootable {
    val port = System.getenv("AKKA_PORT")

    val conf = ConfigFactory.parseString(s"""
      akka.actor.provider = akka.remote.RemoteActorRefProvider
      akka.remote.netty.tcp.hostname = 127.0.0.1
      akka.remote.netty.tcp.port = ${port}
    """.stripMargin).withFallback(ConfigFactory.load());    
    val system = ActorSystem("HelloSystem", conf)

    def startup = {
        system.actorOf(Props[Hello], "hello")
    }

    def shutdown = {
        system.shutdown()
    }  
}

class Hello extends Actor {
  def receive = {
    case msg: String =>
      println("Hello: msg = " + msg)
  }
}
つぎに、Helloにメッセージを投げる側のサンプル
env AKKA_PORT=12345 akka hello.world.Sample.HelloLauncher
env AKKA_PORT=23456 akka hello.world.Sample.HelloLauncher
のように、別コンソールで2つのmicrokernelを起動した前提で動作させる。
object HelloCaller {

import akka.actor.{ Actor, ActorSystem, Props }
    
  def main(args: Array[String]) {
    System.setProperty("akka.actor.provider", "akka.remote.RemoteActorRefProvider")
    // このポートはリモート側でsenderにメッセージを戻す時に使用する
    System.setProperty("akka.remote.netty.tcp.port", "10000")
    val system = ActorSystem("CallerSystem")
    val actor1 = system.actorSelection("akka.tcp://HelloSystem@127.0.0.1:12345/user/hello")
    val actor2 = system.actorSelection("akka.tcp://HelloSystem@127.0.0.1:23456/user/hello")
    actor1 ! "Hello,"
    actor2 ! "Hello,"
    Thread.sleep(1000)
    actor1 ! "World."
    actor2 ! "Another actor."
    Thread.sleep(1000)
    actor1 ! "Yeaaahhh!!!"
    actor2 ! "Hooooooo!!!"
    Thread.sleep(1000)
    system.shutdown
  }

}
なお、mainから呼ぶ側のlibraryDependenciesには、akka-kernel, akka-actor, akka-remote を追加しています。

[sacla] akkaのmicrokernelに引数を渡す

akkaのmicrokernelは、Actorを別プロセスで簡単にバンバン立てられるので、便利なんですけど、今のバージョン(akka 2.3.2)だと、引数を渡せないので困った。

自分はlinuxのコマンドに不慣れで、解決法を忘れそうなのでメモ。

まず、akkaのbinにパスが通っているとして、普通のmicrokernelの起動は
akka com.xxx.packageName.ClassName
でやるんだけど、引数を渡したい時に、
akka com.xxx.packageName.ClassName arg1 arg2
とかやっても、Bootableにargsを渡してくれない。(そういうインターフェースになっていない)
なんでかというと、akkaコマンドが、複数のパラメータが
akka Class1 Class2 Class3
なんてあったときに、3つのBootableを一気に立ち上げるというふうに使っているから(参照)っぽい。

で、解決としては、linuxのenvコマンド(環境を変更してプログラムを実行する)を使用してmicrokernelを
env AHO=xxx BAKA=yyy akka com.xxx.packageName.ClassName
のように起動し、Bootableの中で
  val aho = System.getenv("AHO")
  val baka = System.getenv("BAKA")
とやって引数を取得しました。

2014年2月28日金曜日

[scala] PlayFrameworkでJson文字列の取得で一瞬あせった

Play 使っててJsonの文字列取りたい時、
val jsonObj = ........ とかなんとかあった場合
ドキュメントとか世のブログとかでは、
Json.stringify(jsonObj)
とやれとのことなんだけど、何も考えずに
jsonObj.toString
ってやってて、後で、これでいいの?だめなの?
と疑問に思った。
ちょっと調べたらどうやらjavascriptでは違うらしいので、一瞬
{げっっ!!}
となったが、playのソース(JsValue)を見ると

override def toString = Json.stringify(this)

だってさ。取れるものは同じということで、安心したぜ。

2014年2月14日金曜日

[Java] マイナスの16進数文字列をLongに戻したい

javaで、マイナスの16進数文字列を数値に戻したい。ただそれだけなのに、はまってしまった。信じられん。ということで、運良く解決したのでメモ。
これ、絶対はまるやつ結構いると思うんだけどなぁ。javaめ。

まず、説明のため順序的にLong->16進数ね。
Long l = new Long(-1);
String s = Long.toHexString(l);
これ、当然sが"ffffffffffffffff"。 fが16個。これが欲しいのでOK。
で、今回のお題は、16進数->Longなので、とりあえずこうするわね。
Long rev = Long.parseLong(s, 16);
しかし、ここで実行時エラー。
{なぬーっ。そんなアホなーーっ。}
どうやら、parseLongは、sの中身を正の値だと決めてかかっているようで、"7fffffffffffffff"より大きい文字列を入れるとエラーになる仕様。
Long.decodeも試してみたが、同仕様。
{どうしよう。とほほ。}
ちなみに、
Long ll = Long.parseLong("-ff", 16);
とやると、-255になるんだそうな。誰が喜ぶんだそんな仕様・・・
で、なぜかいろいろググっても解決できなかったのだが、コードをごねごねいじってたらラッキーにも打開策を発見した。
答えは、
Long rev = (new java.math.BigInteger(s, 16)).longValue();
一度、BigIntegerにしてから、それをLongにする。見事revが-1になった。
ナイス、BigInteger.longValue()!!
こいつの仕様に助けられた。
あとは、勝手にlongValue()の仕様が変らないことを祈るだけだ。

2013年11月25日月曜日

[c++11] えっc++って__METHOD__ないの?

プログラム書いてて、エラーメッセージのところで発生箇所のメソッド名を付けたかったんだけど、よくわからんから何となく __METHOD__ とか書いてみたら当然エラーになった。
__func__じゃ短いし、__PRETTY_FUNCTION__じゃ長いので、
// class::method みたいな文字列を取るマクロ
#define __METHOD__ [](std::string s){int sp=s.find(' ')+1;int pa=s.find('(');if(sp>pa)sp=0;return s.substr(sp,pa-sp);}(__PRETTY_FUNCTION__)
ってやったら欲しいのができた。
type_info::name()を使ってもよかったんだけど、デマングルとか面倒くさそうだったので、上の形にした。
自分でよく使いそうなのでメモ。

2013年10月24日木曜日

[c++11] finallyみたいなことしたいけど、専用のRAIIクラス作るの嫌なんだけど・・・

c++には、javaみたいなfinallyがないんだけど、あーゆーの欲しいなーとおもって調べてみると、結局、

・ RAII用のクラス作れよ
・ boost/scope_exit使えよ

ということのようだ、前者はそれ用のクラス毎回作るのもなんだかなーだし、後者はちょっとぐじゃぐじゃしてて嫌だった。

頭に来たので、RAII用にshared_ptrを流用することにしたので、以下にメモっておく。
あ、c++11必須ね。
#include <iostream>
#include <string>
#include <memory>
#include <stdexcept>

using namespace std;
#define FINALLY(CLAUSE) shared_ptr<void> f_i_n_a_l_l_y(nullptr, [&](void*){CLAUSE});

class SomeResource {
public:
 void open() {cout << "some resource open." << endl;}
 void close() {cout << "some resource close." << endl;}
};

int main() {
 try {
  SomeResource res;
  FINALLY(
    res.close();
  )

  res.open();
  cout << "before throw exception." << endl;
  throw runtime_error("xxx error.");
  cout << "end of try block." << endl;
 } catch (runtime_error &e) {
  cout << "Error: " << e.what() << endl;
 }
 cout << "out of try block." << endl;
}
実行した結果は、
some resource open.
before throw exception.
some resource close.
Error: xxx error.
out of try block.
マクロ使って少し見やすくしました。
注意点は、FINALLYを解放したいリソースの宣言と例外が出る可能性のある場所の「間」に入れるところです。

こう見ると、shared_ptrのカスタムデリーターって、いろんなことに流用できそうですね。ちゃんとカウント取ってるからそこの一部のスコープだけに限らず使えるし。
後処理という発想だけでなく、なんかのトリガー的なことに使うと面白そう。

2013年9月12日木曜日

scalaで調子に乗ってfuture{でスレッド量産してたらはまった

注・この記事は、scala2.10を使用しています。

scalaで、
import ExecutionContext.Implicits.global
とfuture使ってて、
「あれ? futureで作った別スレッドの処理がなんか始まらないことがあるんだけど・・・」
ということがある人のための記事です。

scala使ってて便利なのにスレッドを超簡単に作れるってのがあるんだけど、
import ExecutionContext.Implicits.global // どこか上の方でimport

future {
・ なんかいろいろ
・ なんかいろいろ
}
こんな感じね。

ただ単に、future{やると、エラーが出るんで、いろんなサイトのサンプル(こことかこことかここ。みんな良サイト) を参考に、先にimportしてscalaが持ってるデフォルトのExecutionContextであるExecutionContext.Implicits.global を利用するようにしてた。

ところが、調子に乗ってメインのスレッドでやりたくないことをfuture{でがんがん切り離して処理したんだけど、そのプログラムをコア数1のマシンで動かそうとしたら動かない。コア数2のマシンで動かしたらなんか動くけど、プログラムがよく固まる。

固まった状態ではほとんどCPUは食っていない。
ちなみに自分の開発マシンは、4core&ハイパースレッドで8スレッドだったのでその現象は出なかった。
{うげー、マルチスレッド周りの問題は追いかけにくくて嫌だなー・・・}
と思ったのだが、printlnとか入れてみるとどうやら処理がfutureの中身に来ていないようだ。

仕方ないのでサンプルを書いて自機(8スレマシン)で実験してみた。
import scala.concurrent._
import ExecutionContext.Implicits.global

object ThreadSample {
  def main(args: Array[String]) {
    val startTime = System.currentTimeMillis()

    for (idx <- 1 to 24) {
     future {
      println(f"idx = $idx%2d, time = ${System.currentTimeMillis() - startTime}%4d ms")
      Thread.sleep(1000)
     }
    }
    Thread.sleep(3000)
    println(s"end of main.     ${System.currentTimeMillis() - startTime} ms")
  }
}
実行結果
idx =  1, time =   73 ms
idx =  3, time =   73 ms
idx =  8, time =   73 ms
idx =  2, time =   73 ms
idx =  7, time =   73 ms
idx =  4, time =   73 ms
idx =  5, time =   73 ms
idx =  6, time =   73 ms
idx = 13, time = 1099 ms
idx = 16, time = 1099 ms
idx = 15, time = 1099 ms
idx = 10, time = 1099 ms
idx =  9, time = 1099 ms
idx = 14, time = 1099 ms
idx = 11, time = 1099 ms
idx = 12, time = 1099 ms
idx = 21, time = 2100 ms
idx = 23, time = 2100 ms
idx = 20, time = 2100 ms
idx = 19, time = 2100 ms
idx = 18, time = 2100 ms
idx = 17, time = 2100 ms
idx = 22, time = 2100 ms
idx = 24, time = 2100 ms
end of main.     3074 ms
{なんじゃこりゃ、8個ずつしか動いてないじゃん。}
sleepしたからって、次のthreadを処理してくれる訳じゃなく御丁寧にsleepが終わるまで次のスレッドを処理しないで待ってるではないか!
で、どうやらこの同時に動けるfutureの数がマシンのコア数によって変るので、コア数の少ないマシンで自分のプログラムを動かしてた時にfutureで切り離したthreadが実行されなかった模様。

何か他のやり方ないかな、と探していたら、spawnというものがあるようなのでこんなふうに変えてみたら
import scala.concurrent._
import scala.concurrent.ops.spawn

object ThreadSample {
  def main(args: Array[String]) {
    val startTime = System.currentTimeMillis()

 for (idx <- 1 to 24) {
     spawn {
      println(f"idx = $idx%2d, time = ${System.currentTimeMillis() - startTime}%4d ms")
      Thread.sleep(1000)
     }
    }
    Thread.sleep(3000)
    println(s"end of main.     ${System.currentTimeMillis() - startTime} ms")
  }
}
実行結果
idx = 16, time =   56 ms
idx = 23, time =   57 ms
idx =  7, time =   55 ms
idx =  8, time =   55 ms
idx = 21, time =   56 ms
idx = 12, time =   56 ms
idx = 14, time =   56 ms
idx =  5, time =   55 ms
idx = 15, time =   56 ms
idx = 20, time =   56 ms
idx = 19, time =   56 ms
idx = 11, time =   56 ms
idx =  3, time =   55 ms
idx = 13, time =   56 ms
idx =  2, time =   55 ms
idx = 10, time =   55 ms
idx =  1, time =   55 ms
idx = 17, time =   56 ms
idx =  4, time =   55 ms
idx = 18, time =   56 ms
idx = 24, time =   57 ms
idx =  9, time =   55 ms
idx = 22, time =   57 ms
idx =  6, time =   55 ms
end of main.     3058 ms
欲しかった結果になった。しかしコンパイル時に、こんな警告が出た。
[warn] /Users/xxx.scala:97: object ops in package concurrent is deprecated: Use `Future` instead.
[warn]   spawn {
[warn]   ^
{なにー、future使えだとー!?}
仕方ないのでもう少し調べてみると、ちゃんと理解せずに使っていた、
import ExecutionContext.Implicits.global
が元のスレッドの動作を制御していたようで、こいつを変更する必要があった。 しかし、ここで活躍するのが何とjavaのスレッド管理機能であるExecutorsってやつだった。(わかりやすい解説)
で、変更したコードがこれ
import scala.concurrent._
import java.util.concurrent.Executors

object ThreadSample {
  def main(args: Array[String]) {
    val startTime = System.currentTimeMillis()

    val pool = Executors.newCachedThreadPool()
    implicit val execctx = ExecutionContext.fromExecutorService(pool)
 for (idx <- 1 to 24) {
     future {
      println(f"idx = $idx%2d, time = ${System.currentTimeMillis() - startTime}%4d ms")
      Thread.sleep(1000)
     }
    }
    Thread.sleep(3000)
    println(s"end of main.     ${System.currentTimeMillis() - startTime} ms")
  }
}
実行結果
idx = 18, time =   60 ms
idx =  6, time =   59 ms
idx =  5, time =   59 ms
idx =  2, time =   59 ms
idx = 10, time =   59 ms
idx = 13, time =   60 ms
idx = 11, time =   60 ms
idx =  7, time =   59 ms
idx =  8, time =   59 ms
idx =  9, time =   59 ms
idx =  4, time =   59 ms
idx =  3, time =   59 ms
idx = 17, time =   60 ms
idx = 19, time =   60 ms
idx = 15, time =   60 ms
idx = 21, time =   60 ms
idx = 22, time =   61 ms
idx = 12, time =   60 ms
idx = 16, time =   60 ms
idx = 24, time =   61 ms
idx = 23, time =   61 ms
idx = 20, time =   60 ms
idx =  1, time =   59 ms
idx = 14, time =   60 ms
end of main.     3062 ms
で、うまくいった。
Executor辺りのことは、上で紹介したサイトにも書いてあったのだが、そこを読んだときは、ExecutionContext.Implicits.globalで動くんだからいいじゃん。とちゃんと理解してなかった。

ちなみにPlayFrameworkとかいじっててakkaが使える状態のときは、javaのExecutorsを呼ばずに
 val system = ActorSystem("xxxxx")
 import system.dispatcher

future {
・ なんかいろいろ
・ なんかいろいろ
}
で、ActorSystemのdispatcherをインポートしてあげれば、ExecutionContext.Implicits.globalを使わないでいい感じになった。

2013年6月4日火曜日

PlayFramework2.1.1環境で、ScalaからJNAへセットしたコールバックが戻ってこなくなる件

先日の投稿で、scalaからJNAのコールバックを設定するところを
object Tekito {
 lib.setFunction(idx, new JnaCallback {
  def onMessage(msg: String) = println("onMessage " + idx + ": " + msg)
 })
}
こんな感じで書いていたんだけど、実際の環境で上の書き方でコールバックをセットした後、しばらくすると不規則なタイミングでコールバックが返ってこなくなるケースが多発して困っていた。
で、なんとなく次のように変えてみる。
object Tekito {
 def callback = new JnaCallback {
  def onMessage(msg: String) = println("onMessage " + idx + ": " + msg)
 }
 lib.setFunction(idx, callback)
}
これでも状況は変わらず、しばらくするとコールバックが返ってこなくなる。
ただ、コールバックのセットをし直すと、コールバックがまた返ってくるようになることを発見したので、症状が出る前と後で
println(Tekito.callback)
してみると、
正常時
models.Tekito$$anon$1@5ca99bc
コールバックが返ってこなくなった後
models.Tekito$$anon$1@3833089c
{ぬおーっ!アドレス変ってるじゃないかー!}
c側でコールバックを保持しているのは、ただの関数ポインタなので、これではコールバックは返ってこない。
{これ、どうしてくれようか}
と思ったが、素直に下のようにしてみたら
object Tekito {
 val callback = new JnaCallback {
  def onMessage(msg: String) = println("onMessage " + idx + ": " + msg)
 }
 lib.setFunction(idx, callback)
}
こうしてみたら、Tekito.callbackのアドレスが固定されてコールバックが安定して返ってくるようになった。
私は、JVMやscalaのメモリ管理を詳しく知らないので、これで本当にアドレスが固定されるのか確信がないのだが、とりあえず今のところはアドレスが変ってしまうケースはなくなった。
なので、
「scalaからJNAのコールバックをセットする時は、コールバックをvalに入れておく」
をお勧めします。

追記 2013/06/19
後で気が付いたのですが、コールバックオブジェクトを変数に入れておかないと、そのオブジェクトはどこからも参照されていない状態になりGCが動いた時に掃除されてしまうので、コールバックが迷子になる。が正解っぽいです。
コールバックが迷子になるタイミングが不規則だったのは、GCが動くタイミングが不規則だからで、c側でコールバックを保持していてもJVMのメモリとは当然関係ないので、GCに片付けられてしまうということのようです。

2013年5月30日木曜日

PlayFramework2.1.1で動かすakka ActorとWebSocketのサンプル

scala、PlayFramework、akka、WebSocketと初めてづくしで、自分的に、はまりポイント満載だったので、サンプルをあげておきます。
akkaとWebSocketが両方入っていて、サンプルとしては焦点が絞れてないけれど、二つ記事を書くのが面倒なので、そのまんまです。

環境は、PlayFramework2.1.1でscalaもakkaもplayに付属のもの。

まず、初心者がscala、PlayFramework、akkaで一番はまるポイントは、これらは、現在バリバリ進化中の技術なので、ググった情報が古くなってしまっていることが多い、ということ。たった半年前の記事でさえ、古いこともあるので注意が必要です。もちろん、この記事もすぐに古くなりそう。

コードは、PlayのアプリケーションとActorを書いたやつの2ファイル。

・ Playのアプリケーション側
package controllers

import play.api._
import play.api.mvc._
import models._
import play.api.libs.iteratee.Concurrent.Channel
import play.api.libs.concurrent.Akka
import akka.util.Timeout
import akka.actor._
import akka.pattern.ask  // ? の使用に必要!!
import scala.concurrent._
import scala.concurrent.duration._  // 5 seconds の表現に必要
import ExecutionContext.Implicits.global // FutureのonSucceessを使うのに便利
import play.api.libs.iteratee._
import play.api.Play.current // Akka.system を使うのに必要


object AppHelloActor extends Controller {
 val actor = Akka.system.actorOf(Props[HelloActor], name = "helloactor")

 def index = Action {
  Ok(views.html.test("test page."))
 }
 
 def actorWebSocketsSample() = WebSocket.using[String] {
 request =>
 
  def onStart: Channel[String] => Unit = {
     channel => // このchannelを取っておくとclientにいろいろ送信できる
   println("actorWebSocketsSample unicast onStart")
   implicit val timeout = Timeout(5 seconds) // この下の?の隠れ引数のためにここで宣言?! こういう言語は初めてだぜ。
   val future = actor ? "world"
   //val future = actor ? 3.14159 // 上の行をコメントにして、こっちを生かすとonFailureでtimeoutを取れる
   //val future = actor.?("world")(Timeout(5 seconds))
   future.onSuccess {
   case res: Array[String] =>
    res.foreach(value => println("RESULT = " + value))
    channel.push(res.mkString(" ")) // clientにメッセージ送信
    channel.eofAndEnd()
   }
   future.onFailure {
   case e =>
    println("future.onFailure - " + e.getMessage())
    channel.eofAndEnd()
   }
  }

  def onError: (String, Input[String]) => Unit = {
     (message, input) =>
   println("actorWebSocketsSample unicast onError " + message)
  }
  def onComplete = println("actorWebSocketsSample unicast onComplete")
  
  val enumerator = Concurrent.unicast[String](onStart, onComplete, onError)
  
  val iteratee = Iteratee.foreach[String] {
  rcvData =>
   // 今回は、上のonStartで処理終了しちゃってるから何もしてないけど、
   // ここでWebSocketクライアントから受信したデータを処理する。
  } mapDone {_ => println("Disconnected")}
  
  (iteratee, enumerator)
 }
 
}
・ 次は、Actor側
package models

import akka.actor.Actor

class HelloActor() extends Actor {

 def receive = {
  case s: String =>
   sender ! Array(s"Hello, $s.", "Bye Bye.")
     case _ =>
      // timeoutさせたいので、何もしない
 }

}
以上でコードはおしまい。以下、解説、はまったポイント等をだらだらと・・・・

上のコード、importがだらだらとあって省略していないけど、実はここが今回の最重要ポイント。
「webのサンプルと環境が同じはずなのに、コンパイル出来ねぇぜ。大体、こんなメソッドはドキュメントにも載ってないぞ」
とかいうscalaでありがちな状況は、importが足らないのが原因ということが多い。

akkaのActorを使う上で、最初参考にしたのが、
Scalaで並行処理#2 – AkkaのActorを使う
のページで、とてもわかりやすいサンプルと解説の素晴らしい記事。
で、!(投げっぱなし) !!(同期) !!!(非同期)を駆使してやるぞと意気込んでみたものの、!!と!!!のメソッドが見当たらない。
おまけにActor側のself.replyも見当たらない。どうやら仕様変更があった模様。
{まじすか、勘弁してくださいよ先生・・・}
とめげかけるが、akkaの公式ページに解答を発見。(Use With Actorsの項)
どうやら、Actorから、もしくはActorへの通信は、!(返事いらない) と?(返事欲しい)の2種類になったっぽい。たしかにこの表記の方がシンプルでわかりやすい。
前の!!のように、同期で返事を待ちたい場合は、?でもらえるFutureを使って、
val result = Await.result(future, timeout.duration).asInstanceOf[String]
みたいにすれば、結果来るまで待ってられるし、前の!!!のように非同期で結果待ちの時は上のサンプルのように、onSuccessなりonCompleteなり使えばいい。
Futureの使い方についてとても参考になったのは、
Starlight -Little Programmer’s Diary-  Scala 2.10.0 Futures and Promises
のページです。サンプル多くてわかりやすいです。

あと、Actor側のself.replyもsender !になった。
{でも、!ってActorへのメッセージじゃなかったっけ?}
と思ったが、なんと?メソッドが、Actorにメッセージを投げる時に内部で一時的にActorを作ってくれるから、Actorからの戻しも!でいいとのこと。すげー。シンプルだ。
この、scalaとakka開発陣の「仕様変えるな、こら」という声に負けない攻めの姿勢は大好きです。
scalaのことだから、前の書き方でも、たぶん何かimportするだけで動くんだと思う(知らないけど)、これができるのも仕様変更に踏み切れる理由なんだろう。implicit conversion恐るべし。

ただ、上の?メソッドも、ActorRefにも、ScalaActorRefにも見当たらない、これは、コード10行目の import akka.pattern.ask すると使えるようになる。
このimportで、ActorRefがAskableActorRefに、implicit conversionで変身するので?が使用可能になる。これは、確かにわかりにくいが、scalaの拡張性やコードの簡潔さを支えているのが、良くも悪くもimplicit conversionだということがよくわかった。

あと、はまったのが、?メソッドに必要な、隠し変数timeout。scalaには、implicit parameterといって、メソッドに必要な引数を普通に引数として渡すのではなく、周りのコードの引数と同じ型のimplicit宣言された値から取ってくるという、ぶっ飛んだ機能があって、こいつを初めて見たので何のことやらさっぱりわからんかった。
確かにこれなら、せっかく?メソッドが演算子的にかっこ良く書けるのに、timeoutをどう渡すんだよという難問を解決できる。
明示的にtimeoutを渡したい時は、
val  future = actor.?("world")(Timeout(5 seconds))
みたいにもできるが、見にくいし、かっこ悪い。
implicit parameterについては、ひしだまさんのページに書かれた一連のサンプルが非常にわかりやすいです。そのページに限らずひしだまさんのページは、考え抜かれた短いサンプルが大量にあって、scalaを使うには欠かすことができません。scalaの神様です。

で、疲れてきたんだけど、WebSocketにまだ触れてないなこれ。
参考にしたページは、
Auto-Saving ... Done  Play Framework 2.1のWebSocketで一対一通信

server側からclientに送信するには、onStartが呼ばれる時にやってくるchannelを使うので、WebSocketがつながっている間は、こいつを大事に取っておきましょう。
client側から何かを受信するたびに、Iteratee.foreach の中に入ってくるので、ここで簡単に受信データを処理できます。

scalaをいじっていて感じたのは、scala開発陣の、いかに簡潔なコードを作成可能な言語にするかという執念じみたものでした。その執念に、これからも期待したいです。

2013年5月24日金曜日

PlayFramework2.1.1環境で、ScalaからJNA経由でcを呼んだりコールバックセットしたりした

PlayFrameworkを使ったシステムをscalaで書いていて、cを呼びたくなった。
呼びたくなったというよりは、裏でc++でものすっごく激しい計算させるので呼ばざるを得ない。
google先生に聞いても、俺の検索力ではサンプルっぽいものは見つけられかった。
{くぅ。scalaも始めたばっかりで分けわからんし、どうしてくれようか・・・}
とコードをごねごねしていたらなんか動いたので、忘れる前に投稿してみた。

できてしまえば、かなりシンプルになった。もちろん一見シンプルに見えるのはscalaパワーのおかげ。
やりたかったことは、あるクラス(HelloData)の各インスタンスのもつクロージャ(?)をc側にコールバックとして登録して、それぞれのインスタンスからcのライブラリを呼んだ時に、ちゃんとコールバックが呼び出したインスタンスのクロージャに返ってくるようにするということ。

ソースのファイルは5つ
  • Application.scala Play側のmain的な入り口
  • HelloData.scala テキトーなクラス。こいつのインスタンスからcを呼び出したり、ここのコールバックに戻したり、いろんなデータを持ってみたりしてみたい。
  • HelloJna.scala JNAとの接合部分
  • index.scala.html web出力のview部分
  • JnaInterface.cpp c側のソース
以降の部分、ほとんどはコードですが、流れとしては、
Playからindexが呼ばれる→HelloDataのインスタンス作成→HelloDataのコンストラクタ内でコールバック登録→HelloDataのメソッドからcの関数呼び出し→c側からコールバック呼び出し→コールバック内でprintln→c側関数が文字列を戻して終了→webにメッセージ出しておしまい

じゃ、Application.scalaから
HelloDataのインスタンスを3つ作って、ちゃんと区別されて返ってくるか実験する。
package controllers

import play.api._
import play.api.mvc._
import models._

object Application extends Controller {
 def index = Action {
  val data = List(new HelloData(), new HelloData(), new HelloData())
  val msg = data.map(_.callJnaHello)
  
  Ok(views.html.index(msg))
 }
}

HelloData.scala
scala側とc側でデータの連携をとるために、ユニークなidxを持たせてある。
2013/6/4修正 callbackをvalに入れるようにしました。詳しくはこちらの投稿
package models

class HelloData() {
 private val lib = HelloJna.lib
 private val idx = HelloData.cnt;
 private val callback = new JnaCallback {
  def onMessage(msg: String) = println("onMessage " + idx + ": " + msg)
 }
 HelloData.cnt += 1
 
 lib.setFunction(idx, callback)
 
 def callJnaHello: String = lib.getHello(idx)
}

object HelloData {
 var cnt = 0;
}

HelloJna.scala
ライブラリファイルを変更してコンパイルし直しても、一度JVMを再起動(playを再起動すればいい)しないとライブラリをloadし直さないので注意(ここはまった)。JVMには、一度loadしたNativeのLibraryをunloadする機能はないらしい。←あったら誰か教えて
なお、途中のlibHelloJNA.soは、もっと下のJnaInterface.cppからつくったSharedObjectです。
package models

import com.sun.jna.Library
import com.sun.jna.Native
import com.sun.jna.Callback

object HelloJna {
 val lib = Native.loadLibrary("/xxx/yyy/xxx/Debug/libHelloJNA.so", classOf[HelloJnaTrait]).asInstanceOf[HelloJnaTrait]
}

trait JnaCallback extends Callback {
 def onMessage(msg: String): Unit
}

trait HelloJnaTrait extends Library {
 def getHello(idx: Int): String
 def setFunction(idx: Int, callback: JnaCallback)
}

index.scala.html
cの関数から戻ってきた文字列を出すだけ
@(messages: List[String])

<!DOCTYPE html>
<html>
  <body>
 @for(msg <- data-blogger-escaped-messages="" data-blogger-escaped-p="">
 @msg 
} </body> </html>
JnaInterface.cpp
実験なのでidxが255超えたらどうすんのって突っ込みはなし
他の部分はc++で書いていてもここのところはcの関数的に宣言する必要あり(たぶん)。
あと、一番下にiostream閉じてる変なタグが見えたら、SystaxHilighterのバグなので気にしないこと。
#include 
using namespace std;

static int g_cnt = 0;
static char g_msg[256];
static void (*g_callback[256])(const char *msg);

extern "C" const char *getHello(int idx) {
 char callbackMsg[256];

 sprintf(callbackMsg, "msg to callback %d", idx);
 g_callback[idx](callbackMsg);

 sprintf(g_msg, "Hello JNA idx = %d, cnt = %d.", idx, ++g_cnt);
 return g_msg;
}

extern "C" void setFunction(int idx, void (*func)(const char *msg)) {
 g_callback[idx] = func;
}

下は、ブラウザに表示された結果
Hello JNA idx = 0, cnt = 1.

Hello JNA idx = 1, cnt = 2.

Hello JNA idx = 2, cnt = 3.

次は、printlnの出力
コロン前の数字の値は、各HelloDataインスタンス内にあるので、各インスタンス内のクロージャにちゃんとコールバックが戻っているのが確認できる。
onMessage 0: msg to callback 0
onMessage 1: msg to callback 1
onMessage 2: msg to callback 2

2013年4月26日金曜日

[Android] Toastを自分で作ったThreadから表示させる


Toastを自分で作ったThreadから表示させようと思ったらエラーになった。
{まあ、UI Threadじゃないしな}
と思い、ググってみると、そういうわけでもなくLooperなるオブジェクトがあればいいらしい、その辺りの素晴らしい解説が、下のページ

  【Android】 UIスレッドとは別スレッドからのToastの表示

にあって通常そこで終了なのだけど、Looperを取得するために作るHandlerThreadをstart()させた後、quit()するうまいタイミングがないなあと思っていた。
ところが、ApplicationクラスにgetMainLooper()なんてのを見つけたので、使ってみたらうまくいったのでメモ。

Applicationを取得するのには、Activity.getApplication()があるが、今回は違うクラスから別スレッドで動かしたかったので、以下のようにした。

public class MyApplication extends Application {
  static private MyApplication _app;

  @Override
  public void onCreate() {
    super.onCreate();
    _app = this;
  }

  static public MyApplication getApplication() {
    return _app;
  }
}

これを使って、好きなスレッドから、下の関数を呼んで表示成功。