php extensionへの既存C/C++ライブラリ取り込み

最近php extensionを自作する機会が出たので、いろいろと検索しても情報が少なかったのもあってメモ

extensionの作成helloworld的なページ
http://dsas.blog.klab.org/archives/50777398.html
http://dsas.blog.klab.org/archives/50782987.html
http://dsas.blog.klab.org/archives/50903613.html

CPPを含む場合の対応について
http://devzone.zend.com/1435/wrapping-c-classes-in-a-php-extension/

その他参考にしたページ
http://pwiki.awm.jp/~yoya/?PHP/ext#classconst
http://oshiete.goo.ne.jp/qa/7151754.html
http://d.hatena.ne.jp/rikunora2/touch/20100802/1280731016

で、やろうとしたことは既存の静的ライブラリ(.aファイル)をphpで呼び出せるようにラッパーすること。
結論から言うと、PHP extensionの作成でライブラリをリンクするときは、shared objectでないといけないらしい。
静的ライブラリとしてコンパイルした物は使えない。
エラーとしてはこういうものがmake時に出力される模様。

/usr/bin/ld: /path/to/hoge.a(hoge.o): relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC
/path/to/hoge.a: could not read symbols: Bad value
collect2: ld returned 1 exit status
make: *** [huga.la] エラー 1

「-fPIC」というオプションをつけろということらしい。

for文のループ方法について

まとめサイトを巡ってたら気になるコメントがあったので試してみたメモ。

http://blog.livedoor.jp/itsoku/archives/41660022.html

このコメント73の「デクリメントのほうが演算コストが云々・・・」の部分。
このあとすぐに「マシン語レベルだと変わらない」と判断されてたけど、実際どうなのか確かめてみようかと。
コンパイルとかも面倒だったんでとりあえずnode.jsで。

var MAX = 100000000;

var start = new Date().getTime();
for(var i = 0; i < MAX; i++){} // (1)
var end = new Date().getTime();
console.log("for(var i = 0; i < MAX; i++){} : " + (end - start) + "(msec)");

var start = new Date().getTime();
for(var i = MAX; i; i--){} // (2)
var end = new Date().getTime();
console.log("for(var i = MAX; i; i--){} : " + (end - start) + "(msec)");

やってみた結果、前者は96msくらいで、後者が126msくらい。
後者のほうが若干遅くなる模様。

他の言語でやってみた場合どうなるか気になるなあ。


11/03 00:03追記

C言語で同様のコードを試してみたら(1)が230ms、(2)が210msだった。
i < MAXの比較処理分の差が出たのかなあ。

findAndModifyについて

MongoDBのクエリの一つ、findAndModify
便利なクエリなんだけど、制約も多いのでメモ。
MongoDBのドキュメントにも載っていることなので、詳しくはそちらを。

  • 更新は1ドキュメントのみ

要はfindOneして見つかったデータのみ更新されると思えば良い。
こんなかんじのクエリを実行しても、更新されるのは最初の1件のみ。

db.test.findAndModify({query : {hoge:{$in:["a", "b", "c"]}}, update : {$set:{foo:100}}})
  • shard keyを含まないクエリはエラーになる

これは知らずにやってしまうと結構問題になったりするかも。ローカルの環境ではshardingなんてやらないことがほとんどだと思うので。
sharding構成をとっている場合、検索のキーにはshard keyを含む必要がある。
これを満たしていないと問答無用でエラーにる。

// shard key : "hoge"の場合
// これはOK
db.test.findAndModify({query : {hoge:"a"}, update : {$set:{foo:100}}})
// これはアウト
db.test.findAndModify({query : {piyo:"a"}, update : {$set:{foo:100}}})

vimにコピペするときの自動インデントとか自動コメントアウトとか

(放置してたので久々にネタというか記事を投下)

何かvimでテキスト、特にシェルスクリプトとか簡単なコードをペーストするとき、
オートインデントや次行の自動コメントアウト設定が入っていると大変なことになったりする。
元の設定を外せばいいんだろうけど、共有のアカウントを使っていて外すに外せない、なんてこともあったりする。
で、自動でインデントなどが入らないようにするやり方はこれ。

:set paste

ペーストモードになって、「テキストをそのままの形式で」貼り付けできる。
何度か出くわすたびに調べてたのでメモ。
大本の設定でどうにかするやり方はググろう(丸投げ)

DocumentRootが存在しない状態でgraceful

セットアップをしていてふと気になった。
調べるよりやってみた方が早いか、と思って仮想マシンでテストしてみた。

試してみたのはApache2.2系。

実際にやったところ、warningがでてgraceful自体の動作が中止さた。
再起動は行われず、今まで動いていたapacheのプロセスがそのまま動き続けるらしい。
色々とアクセスしてみて検証してみた感じ、graceful前の状態のものがそのまま動いていた感じ。


詳しい人に話してみたら
「昔は落ちた気がしたけど、どこかのバージョンでそこの動作が良くなったのかなあ」
って言ってた。

オブジェクトの代入

JavascriptのObjectやArrayは代入すると参照コピーになってしまう。
つまりこういうことをやってしまうと

var hoge = {a : 100};
var piyo = hoge;
piyo.a = 1024;
console.log(hoge.a); // 1024

hogeとpiyoは全く同じものなので、piyoだけ書き換える、ということができない。

中身の値だけコピーしたい場合はこうすればいい。

var piyo = JSON.parse(JSON.stringify(hoge));

中身のfunctionもまるっとディープコピーする場合は
ちゃんと再帰的に走査してコピーする関数を作らないといけない。


ちゃんと代入されてるはずなのに・・・?と小一時間ほどハマっってしまった。
調べて初めて知ったよ。

俯瞰の風景と初めての3D

土曜日に空の境界 俯瞰風景3Dを見てきた。
俯瞰風景を映画館で見てから6年もたってるんだなあ・・・

ゼロカフェは海魔が意外と可愛かったw
10分程度ながら面白かったんで、別のお話を見てみたいと思った。

本編の方はすでに見たことあるとはいえ、相変わらずのクオリティだった。
ただ、3Dの映画に関しては今回が初だったんだけど、正直「こんなもんかー」というのが感想だった。
もともと3Dのために作られた作品じゃないし、仕方ないのかな。
飛び降りるところとか、雰囲気は良くなってた気はするんだけど。

見終わったあとは、デレた式の破壊力を再確認しました。



実は上映中、3Dメガネの方の構造に興味が行ってたりする。
電池を入れるような部分があったし、シャッター方式なのかなーと思って帰ってから調べたら、やっぱりシャッター方式だった。
シャッター方式ってもっとごついメガネなのかなと思ってたから、見た目シンプルで驚いた。