2017/09/29

[btc]bitcoinはあやしいのか、という話はあまり意味が無いと思う

正直なところ、どうでもよい話なのだが、ネタが無いので。

Googleニュースで、キーワードを設定しておくと適当に拾ってきてくれる。
「bitcoin」「blockchain」などのキーワードを設定していると、それなりにニュース記事を拾ってきてくれるようだ。
比較的新しいけど、最新というわけでもないから、閲覧されている順番とか、そんな順かもしれない。

ニュースの内容は、だいたいこういう感じだろうか。

  • どこかが実証実験した
  • どこかがブロックチェーンで何かすることにした
  • 仮想通貨に関する誰かの意見

意見の記事は、かなりの確率で仮想通貨に否定的な内容だ。
あやしいとか、バブルだとか、信用ならないとか、バブルだとか・・・。


まあ、気持ちはよくわかる。

その方面の技術の人じゃなかったら内容を判断することができないので、投資・投機だけやっている人は困るだろう。
今までの知識が役に立たないとき、だいたいは拒否する方を選ぶものだ。

銀行みたいにお金を取り扱うところは、また訳のわからんものが出て・・・と思うかもしれない。
あまり日本の銀行には技術者が多くないという話を聞くので、技術的に分からなければ遮断する方向に行ってしまうだろう。

逆に、技術の人からすると、価値が上がったり下がったりするのは技術のせいじゃないので、知ったことではないと思う。
私はbitcoinしか見てないので、最近はやりのICOなんかは詳しくないのだが、見る人が見るとあやしいものはわかるんじゃないかと思う。
ソースが公開されていれば内容を調べればよいし、公開していないなら調べようがない、というだけだ。


そういう感じだと思うので、全部に通じているような人じゃなければ、あまり相手にしない方がよいかもしれん、とは思う。
私も技術だけしかわからないので、もうちょっと視野を広げないとなー、という気持ちだけは見せている。


仮想通貨は、株式よりも外貨取引に近いと思う。
ただ、どこかが発行しているものではない、というのが「仮想」なのか。

この部分が「発行しているところがないお金なんて信用できない」と「発行しているところがないので安心」のどちらかになるんじゃなかろうか。
そこに価値を見いだす人は買うだろうし、見いださない人は買わないだろう。
買う人が多いと、需要が増えるから、価値が上がる。


ただ、価値が上がった下がったといっても、技術自体がなくなるわけじゃない。
もし、あれこれあって、bitcoinが使えない状態になってしまったら、面倒だろうけど、別の安定した仮想通貨で技術を延ばすだけだ。
bitcoinはわかりやすくて気に入っているのだが、まだまだ私もこの分野では新米なので、あれこれ学んだ方が良いのかもしれんしね。


ごにょごにょ書いていったが、

  • 全体的に見て、よいと思うのであれば、認めてよいのではないか
  • よくわからないなら、そのまま触らなくても問題ないと思う
  • 金儲けの手段としてしか見ない人がぐいぐい言ってきたら、仮想通貨よりも人格を判断した方がよい

というのが今のところの感想だ。

2017/09/27

[c/c++]メモリリークしていると思うが、どうしたものか

アプリのバージョンアップで変更履歴を見ると、ときどき「メモリリーク修正」みたいなものがある。
メモリリークなんて、最初からがんばればよかろうに・・・と若い頃は思っていた。

というよりも、組込みソフトの場合、動的にメモリを取らず、静的にメモリを確保することが多いので、気にしていなかったのかもしれない。
静的に取ることが多いのは、

  • そもそも動的メモリがない(mallocがないなど)
  • 同時に動的メモリを確保して足りなくなることがあってはいけないので、最初から確保しておく

などという理由なんじゃないかと思う。

私の場合は、mallocが無いので、そもそも動的メモリという選択肢がない、という場合が多かった。
まあ、OSが載ることもほとんど無いしね。


ここ半年くらい、PCのLinuxでソフトを書いている。
もちろん、mallocなんか普通に使える。
同時にメモリを確保して足りなくなるなんてことが、ほぼない。
そもそも、PC Linuxで作ることを前提にしているので、リソースは十分にあるものという仕様になっている。
であれば、動的メモリを使わない必然性がなくなってしまう。


なんとなく気付いたかもしれないが、私は動的メモリが苦手なのだ・・・。
なるべくがんばったので、やったことを書いておこう。


前提として、C言語のみ、だ。


malloc系のAPIとfree()をマクロにした

出落ち感があるが、これに尽きる。

マクロにしておくと、例えばmallocしたところを__FILE__と__LINE__で出すことができる。
inlineにしていても、これはできないと思うのだ。

static変数を使って、通過したカウンタなんかを付けるのもやる。
malloc系でインクリメントして、free()でデクリメント。
全部解放していると思っているところでカウント値を見れば、簡易的なチェックには使える。



valgrindする

してたんだけどねぇ。。。
とにかく、終了するアプリじゃないので、valgrind結果を見るタイミングがない。
unit testのときには使えるのだけど、mallocするタイミングとfreeするタイミングが別々になることが多くなると、unit testでは漏れが確認できない。

というよりも、アプリが終了しないので、動的にチェックできたとしても、今が解放されているべきなのか、そうでなかったらいくつ確保されているべきなのか、というのは状態によって異なるので、結局ログを全部追わないとわからんかったりする。

デストラクタとかガベッジコレクションのある言語が憎たらしくなるのは、こういうときだ。


しかし、もう2017年も後半になってきた。

実は、私が知っている手段以外によいものがあるかもしれない。
それに、オライリーの「Debug Hacks」から読み直すべきかもしれん。
組込みで使えそうなところ以外は読んでいないからだ。

2017/09/20

JavaScriptの整数範囲はJSONに影響するのか?

以前、JSON-RPCをやるのにuint64_t対応したライブラリが見つからない、という話を書いた。

結局、内部でしか使わないからいいや、ということで、jsonrpc-cをforkして、uint64_tにだけ対応させることにした。


それはそれでよいのだけど、世の中にはあるんじゃなかろうかと探していた。
同じ疑問を持つ人がいた。
c++ - Does libjson support 64 bit int types? - Stack Overflow

libjsonは知らんのだが、回答からすると、JavaScriptは内部的に53bitまでの制限があるよ、ということらしい。
ECMAScript仕様のページにリンクが貼られていて、確かにごにょごにょ書かれている。


こちらは、ECMAのJSON仕様(pdf)だ。
ただ、JSONのtext format仕様なので、値の範囲がどうのこうのということは書かれていない。


だから、やはり安全にいくなら、uint64_tは文字列にする方がよいのだろう。
32bitずつにして、上下で表してもよいかもしれんが、とにかく表せないかもしれない書式を使うのは危ないかもしれん。
まあ、そんなことをいえばint64_tだって53bit以上あるのだから同じことか。


それだったら、いっそのこと全部の数字を文字列で表せばいいやん、みたいな気持ちになってしまうので、深追いは止めよう。
大人の対応というのは、最終的に自分への負担が減る対応にするべきなのだ。。。

2017/09/18

[vscode]gdbを使ってみよう(2017/09/18)

コンパイラとしてgcc系のものを使うことが多いので、デバッグもgdb系になる。
が、何十年もやっていながら、未だにgdbに慣れていない。。。

だが、世の中にはGUIで隠してくれるデバッガもある。
dddやinsight、eclipseもプラグインで対応できる。
nRF51をデバッグしていた頃はeclipseを使っていたのだが、起動が重たいので、動かすかどうかをためらうこともあった。

最近、Visual Studio Code(以下、vscode)を使うことが多くなったので、そっちでも同じようなことができそうな気配がする。
まずは、vscodeでgdbを使ったデバッグをしてみよう。


vscodeは更新が多く、また機能をextensionsで実現することも多いため、最新版ではここに書いていることが使えなくなっているかもしれない。

こちらは、2017/08/18に更新されているので、これを眺めながらやっていく。
C++ Programming | Visual Studio Code Docs


ビルドはコマンドラインでやってもよいのだが、せっかくなのでvscodeからやってみよう。
昔やった、lmdbのサンプルコードがあったので、それで試していく。
コード自体はどうでもよいのだが、Hello Worldみたいなサンプルではわかりづらいので、多少込みいったものを選んだだけだ。


サンプルは、こうやってビルドできた。

$ gcc -o tst ex1.c -llmdb -pthread

そのフォルダでvscodeを起動。

$ code .

ファイルで開くとダメそうな気がするので、ディレクトリ指定で開くとよいかもしれん。
その状態で Ctrl+Shift+B を押すと、タスクがないよ、というメッセージが出てくる。
「Configure Build Task」の方をクリックすると、4択になるので「Others」を選択。
すると、.vscode/tasks.jsonというディレクトリとファイルを作ってくれる。

tasks.jsonは、こんな感じで書く。

{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        {
            "taskName": "gcc",
            "type": "shell",
            "command": "gcc -Wall -ggdb -o tst ${relativeFile} -llmdb -pthread",
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "problemMatcher": {
                "owner": "c",
                "pattern":[
                    {
                        "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$",
                        "file": 1,
                        "line": 2,
                        "column": 3,
                        "severity": 4,
                        "message": 5
                    }
                ]
            }
        }
    ]
}

リンク先よりもversionが上がっているので、変わりやすいのかもしれん。


"group"を書いて、"kind"を"build"にしないと、Ctrl+Shift+Bでビルドしてくれなかった。
"problemMatcher"を書いておくと、それに引っかかった出力がタブ「PROBLEMS」に出てくれる。
${file}だとフルパスになるためか、PROBLEMSをクリックしてもファイルがないと言われてしまった。
${relativeFile}だとvscodeを開いたディレクトリからの相対パスになるようで、そっちだとOKだった。


makeしたい場合は、こんな感じで書いた。

{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        {
            "taskName": "make",
            "type": "shell",
            "command": "make",
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "problemMatcher": {
                "owner": "c",
                "pattern":[
                    {
                        "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$",
                        "file": 1,
                        "line": 2,
                        "column": 3,
                        "severity": 4,
                        "message": 5
                    }
                ]
            }
        }
    ]
}

ただ、これは統合開発環境じゃないから仕方ないのだが、problemMatcherは出力をなぞるだけのため、Makefile内でディレクトリ移動してMakefileを呼び出す、みたいなことをやっていると、ファイルを見つけられないようだ。

make用のExtensionsがあるのかもしれんが、まあ今回はよかろう。


次はgdb。

https://vscode-doc-jp.github.io/docs/languages/cpp.html#%E3%83%87%E3%83%90%E3%83%83%E3%82%B0
https://code.visualstudio.com/docs/languages/cpp#_debugging-your-code

どっちを見ても、launch.jsonというファイルを作れ、と書いてある。
仕方ないので、.vscodeディレクトリで右クリックし、「New File」でlaunch.jsonを作った。
そうするとlaunch.jsonファイルがタブで開き、右下辺りに「Add Configuration...」というボタンが出てきた。

ボタンを押すと、versionなどのテンプレートが出てきたので、Enterを押して確定。
まだボタンが出ているので押してみると、追加する中身のテンプレートが選べるようだった。
せっかくなので、C++のLaunchするやつを選択。
これはありがたい。


と、ここまでやってリンク先を見たら、Debug Viewにしてやればファイル作成などは勝手にやってくれたみたいだ。。。
悔しいので、.vscode/launch.jsonを消してやり直す。

まず、左側のデバッグっぽいアイコンをクリックし、Debug Viewにする。
設定してくれそうなアイコンが出てくるので、クリック。
そうすると、さっきのような選択が出てくるので、C++のgdbできそうなものを選択。
まあ、できるファイルは同じっぽいな。


"program"は書き換えないといかんだろう。
"${workspaceRoot}/tst"にする。
ファイル保存して、Viewにあるデバッグ開始しそうなアイコンをクリック!

・・・開始エラー?
よくわからんのでもう一度押すと、今度は動いて、設定していたブレークポイントで止まったようだ。
たぶん、launch.jsonの"stopAtEntry"を設定しておくと、その関数で止まるようになってるんじゃなかろうか。


変数名にマウスを当てると中身が見えるし、構造体も出てくれる。
整数型は10進数で、ポインタは16進数で表示するようだ。
16進数で見たい場合は、WATCHとして追加するしかなさそうだ。
例えば、env->me_flagsという値を16進数で見たかったら、「env->me_flags,h」のように指定するそうだ。
https://github.com/Microsoft/vscode-cpptools/issues/379

2016年12月のことだから、今は別の手段があるかもしれん。。。が、それっぽいのは見つからなかった。
まあ、こういうのは、だいたい解決されていくものだし、方法がないわけではないからよかろう。


こんな感じで、gdbを使うだけであればlaunch.jsonを作るだけでよさそうだ。

2017/09/17

[btc]confオプションはフルパスで書くべし

testnetでなかなかマイニングされないので、regtestに切り替えようとしている。
まあ、testnetは有志によるものっぽいから、何が起きても文句は言えない。。。


まず、testnetとregtestを同時に動かしておけるかどうか。
これは、ダメそうだ。
bitcoindがHTTP serverになるようで、2つめを起動したらエラーになった。

Error: Unable to start HTTP server. See debug log for details.

引数で何か設定すればよいのかもしれんが、まあそこまで切実ではないので、よかろう(実はできるのだが、後述)。


次は、confファイル。
bitcoindはデフォルトで~/.bitcoin/bitcoin.confを見に行くが、regtestのために書き換えるのが面倒だから、regtest用のconfファイルを読み込ませたい。

regtest=1
server=1
txindex=1
rpcuser=xxx
rpcpassword=xxxxx
rpcport=18443

こんな感じか。
rpcportを設定したのは、まあ、確認みたいなものだ。

$ bitcoind -conf=./regtest.conf

そして別のコンソールから確認。

$ bitcoin-cli -conf=./regtest.conf getblockcount
74242

ん??
regtestなのにブロックがあるし、やるたびに増えていってるからどこかからダウンロードしているようだぞ。
networkinfoで見ると、やはりピアが見えているし、ポート番号も8333だ。
ということは、mainnetを見に行ってるらしい。


こうやるのがよさそうだ。

$ bitcoind -conf=./regtest.conf -regtest

納得がいかないのだが、仕方ない。

regtest.confから「regtest=1」を削ってもよいかも。
ただ、bitcoin-cliの方は-confで設定したregtestを見ているようで、-regtestオプションを付けなくてもよいようだ。
まあ、bitcoindが付けているのだから、両方付けた方が統一されていてよいかもしれん。


では、最後にJSON-RPC。

$ curl --user xxx:xxxx --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getblockcount", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:18443/

ダメだ、接続できない。
wiresharkでbitcoin-cliしたときのポートを見ると、18332になってる。
全然confファイルの言うことを聞いてくれんやつだ。。。

そして、ポート番号を18332にしてもダメ。
認証に失敗しているようだから、rpcuserなんかも見てないということか??
しかし、getnetworkinfoで見ると、なんか18444を監視している。
いっちょんいうことばきいてくれんっちゃけんねぇ。。。


このregtest.confを、カレントディレクトリではなく~/.bitcoinの中に置き、-conf=regtest.confとディレクトリ無しにすると、すんなり動く。
-regtestもいらないし、JSON-RPCも書いてある通りの設定になる。
よくわからんが、その方がいろいろやるよりも安全な気がする。


自動実行するときは、systemdに登録しているのだが、そのときはたぶんUserで指定した人の~/.bitcoin/bitcoin.confを使っているのだろう。
ここを見ると、/etc/bitcoin/bitcoin.confを例にしているので、そういうのはありなんだ。。。
https://github.com/bitcoin/bitcoin/blob/master/doc/init.md

systemdのservice設定を見ると、conf指定だが、フルパスで書いているな。
https://github.com/bitcoin/bitcoin/blob/master/contrib/init/bitcoind.service

まさか・・・。

$ bitcoind -conf=`pwd`/regtest.conf

はい、そういうことでした。
confはフルパスで書くべし、でした。

最初に試した、testnetとregtestを同時に動かす、もconfファイルを相対パスで指定していたのでうまく動いていないだけだった。
datadirを別にすれば、regtestを複数立てることもできるんじゃなかろうか。意味はなさそうだがね。

2017/09/16

[bow]lmdbのmdb_env_open()でエラーになる

msg queueを使うプログラムを作っていたのでUbuntu16.04で作業していたのだが、socketに変更したので今のbash on Ubuntu on Windowsでも動かせるようになったんじゃなかろうか、ということでやってみた。

・・・そこに行き着く前に、lmdbのmdb_env_open()でエラーが返ってきた。。。


エラーの内容は、exec format error。
ENOEXECというやつだ。

ずーっとたどると、mmap()でエラーを返しているようだった。
gdbを使わず、printfデバッグで探していたので、たどるのが大変だった・・・。
GUI環境じゃないところで、まだgdbを使えないのだよ、私は。


この辺りかな?
mmap's problem · Issue #658 · Microsoft/BashOnWindows

いろいろ書いてあってよくわからんが、まあ、たぶんbowのバグなんだろう。
2017年秋バージョンに期待だ。

[btc]testnet3

bitcoindでは、ほとんどtestnetを使っている。
bitcoin.confにも「testnet=3」と書いている。

が、btcdなんかは1と書く(3だとエラー)。
つまり、testnetは実質、testnet3しかないというになるだろう。

そもそも、testnet3ってなんだ??


Testnet - Bitcoin Wiki

このページの最終更新日は2017年2月8日なので、新しいといってよいだろう。

testnetには3つあります。

testnet2は、testnetと異なるgenesis blockを持つ最初のtestnet resetだ。
testnet3は、現在のtest networkだ。

2行目の訳が怪しいので、原文を読んでおくれ。
とにかく、初代testnet、testnet2、testnet3があり、今はtestnet3ということだ。

引数だって「-testnet」だし、bitcoin.confが「=1」でも「=3」でも特に動作は変わらないようだ。
bitcoindでも、bool扱いしているように見えるから、0でなければtestnetになるんじゃなかろうかね。

2017/09/14

[tech]IPFS

世の中にはいろいろと技術があり、「これどうやってるんだろう??」というものも多い。
IPFSも、私にとっては「ど、どうやってるんだ??」という技術の一つだ。

なんというか、ブロックチェーンと非常に似たものを感じる。


ブロックチェーンでの開発を行っていると、何かに依存した状況を極力作りたくない。
「ああ、この情報をサーバに置きさえすれば解決するのに・・・」と思ったとしても、それをやってしまうと依存が生じてしまう。
まあ、多少はよいか、という考え方もあるのかもしれないが、やっぱりここまできたらねー、という意地みたいなものも出てくる。


そこで、IPFSだ。
全然技術的に理解はできていないのだが、ファイルをアップロードすると、適当にファイルを分割されて、適当に冗長性を持たせつつ、適当に分散させて、ノードを提供している人たちに持たせている。
たぶん、ブロックチェーンのフルノードみたいに、全員が同じものを持つ、というものではないように思う。
また、単に分割してばらまくわけでもなさそうだ。

それを取得するには、アップロードしたときに渡されるハッシュ値を使う。
ファイル名に相当するのかな。
それを使うと、そのハッシュ値に相当するものがファイルとして取得できるようだ。


サイトにある「Try it」を試しただけで、それ以上は入り込んでいない。
私がやったときは、子猫の画像が取得できた。


まあ、Bitcoinのブロックチェーンだって、こんだけ人々がアクセスしてもハッシュ値でトランザクションが一意に表せているので、IPFSの参加者くらいであれば十分にまかなえているのかもしれないし、ハッシュ値のサイズだって違うかもしれない。

だから、ハッシュ値でファイル名の代わりにする、という考え方はまだわかるのだが、残りの重要な部分はさっぱりわからん。
RAIDみたいな感じを持ってしまうけど、たぶんどこかのIPFSノードが動いていないくらいだったら問題ないんじゃなかろうか。


これは、なんというか、ぞくぞくする怖さを感じましたな。
こういう技術が生まれてくることに、まだまだ視野が狭かったなー、と感じざるを得ない。
いや、自分で生み出せたかも、とかじゃなくて(無理無理...)、世の中で未発見のものは、発見されたとしても私には理解ができないものなんじゃなかろうか、などと考えていたことに対してだ。

一般技術者としては、その発明/発見に敬意を表しつつ、理解し、より使いやすい形にしたり、安全にしたり、応用したりするのがまっとうなやり方かな、と思う。

2017/09/11

[c/c++][linux]stdoutへのリダイレクトが期待通りにできない

共通で使っている処理があり、そこは出力を標準出力に行っている。
ただ、一部だけ、どうしてもファイルに掃き出したいと考えた。
元の方は書き換えたくなかったので、呼び出し元で標準出力をファイルにつなげてやればよいだろう。

この処理は何回も呼び出し、それぞれ別のファイルに出力したい。
だから単純なリダイレクトではないのだけど、まあclose()してやるだけだろう。。。


うまくいかなかった。

リダイレクトを分割したいが、うまくいかない

ファイルは3つできるのだが、中身は3.txtにしか入っていない。
そして、3.txtには全部の出力が入っているのだ。
fdをclose()させていないが、あんまり関係が無かった。

標準出力は出力タイミングまでバッファにためるタイプだったはずなので、SYNCっぽいものをあれこれ追加したのだが、どれもダメだ。


じゃあ、標準エラー出力だったらバッファにためないからいいんじゃなかろうか、ということでやってみると、OKだった。

stderrならうまくいく


ということは、システムコール側ではなく、もっと上位層で制御されているということか。
ならば、ファイルディスクリプタの1をfsync()するのではなく、stdoutの方をfflush()したらいいんじゃなかろうか?

fflush(stdout)するとOK

OKだった。
なるほどねぇ。


ただ、一部だけリダイレクトさせるのも格好が悪いので、結局実装としては別の関数にしてFILE*を取るようにしたのであった。

2017/09/09

[zybo]PetaLinuxでDigilentのチュートリアルが動かん (19) : 完

動かん(18)で、XSDKでRunした場合はZyboのLinuxではなく、素の環境で動いているんじゃないか、という疑惑が発覚した(私の中で)。

素の環境というのは、リセットベクタから起動した後、OSを介さずにC Runtimeだけ動かし、すぐにmain()から動き始める、という意味だ。

バイナリの種類が違いそうだというのは、fileコマンドの結果によるものだ。
PetaLinux用の/bin/bashと比較しよう。


$ file bash
bash: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 3.2.0, BuildID[sha1]=bf9ec80803a2f03da139c81eddb5bc276cb5250b, stripped


$ file hello.elf
hello.elf: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, not stripped


dynamically linkedかstatically linkedだけでは判断できないのだが、「for GNU/Linux」とまで出力されては、違いがあることを認識せざるを得まい。


Windows版のXSDK v2017.2には、どっちのコンパイラもあるようだ。

image

aarch32は、archがARM32bit版の意味かな?
他にもフォルダがあり、aarch64やmicroblazeもある。
こんだけコンパイラがいっぱい入っていれば、ダウンロードサイズも大きくなるわな。。。

単なるarmフォルダもあり、こっちはarm-xilinx-eabiやarm-xilinx-linux-gnueabiもある。

SDK\2017.2\gnu\arm\nt\bin>arm-xilinx-linux-gnueabi-gcc --version
arm-xilinx-linux-gnueabi-gcc (Sourcery CodeBench Lite 2015.05-17) 4.9.2


SDK\2017.2\gnu\aarch32\nt\gcc-arm-linux-gnueabi\bin>arm-linux-gnueabihf-gcc --version
arm-linux-gnueabihf-gcc (Linaro GCC Snapshot 6.2-2016.11) 6.2.1 20161114

ほー。
久しぶりにSourceryという名前を見た。


選択は、プロパティ画面で、「C/C++ Build > Tool Chain Editor」からできそうだった。

image

何も考えずに作ったプロジェクトは、上の図のように選択されていた。
プロジェクトは新規作成したので、どこかで選択できるようになっているはず。

これか。

image

OS Platformがデフォルトで「standalone」になっていたのだ。
これが「linux」ならよいのか。


「linux」にすると、何やら更新が行われ、少し設定項目が変わったようだ。

image

Windowsでやるときも設定できるのだろうか?
そのままウィザードを進めると、テンプレートから空アプリかhelloworldかが選べるので、今回はhelloworldを選択。
自動でビルドしてくれるので、できているELFファイルをSDカードにコピーして、PetaLinux起動。
Zyboで立ち上げて、実行。

・・・動くやん。。。


20回に達する前に解決してよかった、と前向きに考えよう。
長い連載で理解したのはこういうことだ。

  • XSDKでアプリのプロジェクトを作るとき、デフォルトでは「standalone」になっていて、これはOS無しで動くバイナリ
  • OS設定を「Linux」にすると、Windows版のXSDKであってもARM Linuxで動くELFファイルを作ってくれる
  • PetaLinuxのCustom moduleではxparameters.hを読んでくれないので、なんとかせんといかんようだ

なお、どのコンパイラが選択されているかは、XSDKのPreferencesにある「Xilinx SDK > Toolchain Preferences」から確認できそうだ。

image

ZynqはCortex-A9だったと思うので、Linaroがデフォルトのようだ。

[zybo]PetaLinuxでDigilentのチュートリアルが動かん (18)

18回目になるのに、まだ解決しないとは・・・。
いや、そもそも最初の目的はなんだったっけ?

第1回を見ると、Zyboのチュートリアル通りにやってみたものの、EclipseベースのSDKから実行すると動くのだが、実行ファイルをPetaLinux上にコピーして実行してもIllegal Instructionが発生した、ということのようだ。
じゃあPetaLinuxの環境でビルドせんといかんのじゃなかろうか、と。
まずは簡単なものから、と考えて見ていったら、Interface誌にJEポートをGPIO制御するドライバサンプルがあって・・・、というのが、現状だ。


しかし、XSDKのベースとしている環境を変更する、という方向もありかもしれん。
せっかくXSDKがあるのだから、コマンドラインでビルドするPetaLinuxはLinux環境やドライバまでで、アプリはXSDKでやっていきたいではないか。


久々にXSDKを立ち上げ、helloworldアプリをビルドした。
そして、XSDKからRunさせると、ちゃんと"Hello Wrold"がコンソールに出力される。
ここでいうコンソールは、ZyboのUSBをPCに接続して開いたTeraTermのUARTコンソールだ。

そのhello.elfを、ビルドしたPetaLinuxが入っているSDカードにコピーして実行すると、やっぱりIlletal Instructionになる。
Zyboチュートリアルのときは、ハードウェアが関係して、不正なアクセスか何かが発生してダメなのかと思っていたけど、そうではないということか?


まずは、fileコマンドで確認しよう。
PC Linux上で確認する。

$ file hello.elf
hello.elf: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, not stripped

staticリンクだから、ライブラリがないということではないだろう。
まあ、そうだったら別のエラーになるはずだ。


Illegal Instruction | Zedboard

む、「Linux Application」と「Standalone Application」の違いがあるのか。
よく考えれば、XSDKから実行するときは、ZyboにLinuxが立ち上がってなくても動作しているし、XSDKからLinux環境ごと転送して起動させているような様子もない。すぐ実行されるし。

ということは、このELFファイルはLinux環境向けではない・・・?
普通のLinux環境向けバイナリはどうなるんだっけ。。。

$ file /bin/grep
/bin/grep: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=a28bf08898e693819102c974c8e54fdcf6f8a7a6, stripped

ああ、そうなのか。。。
XSDKってなんとなくLinux用のバイナリを作ると考えていたのだけど、よく考えたらFreeRTOSもサポートしているので、素のバイナリも生成することができないといかんのか。


コンパイラ変更とかでよいのかしら?
解決は次回にして、今回はここまでにしよう。

2017/09/08

[btc]TXIDとSegwitのTXIDとWTXID

TXID、というものがある。
Transaction IDの略だ。

IDというと、どこかで管理したりしていそうだが、Bitcoinはどこかに依存することがないというか、全体に依存しているというかで、データのためのデータはそんなにないと思う。

ただ、トランザクションを一意に表す数字がないと不便なのも確か。
だから、トランザクション自体のデータからハッシュ計算してIDを求めている。


さて、Segwitが出る以前。
TXIDはシンプルで、トランザクションデータ全体をSHA256し、それをさらにSHA256した値(32byte)だった。

トランザクションの構成は、こうだ。

  • version
  • txin
  • txout
  • locktime

bitcoindでトランザクションを作ったことがある人はわかるだろうが、順番としては、

  • 署名が空のトランザクションを作る
  • 署名する

という手順を踏む。
署名したトランザクションはブロックチェーンに公開することができるので、署名するのは最後なのだ。
だから、TXIDが計算できるのは署名後ということになる。


さて、時代はSegwit。
Segregated Witnessという名前の通り、署名が分離されたトランザクションになる。
トランザクションから分離したということは・・・TXIDからも分離されたのだ(そういう理屈なのかどうかは、知らん)。

しかし、トランザクションデータには署名が入っている。
細かく言えば、txメッセージで送信するトランザクションデータには署名が載っている。
ではSegwitなトランザクションのTXIDはなんなのかというと、計算方法が以前と異なるのである。
計算式はシンプルなTXID時代からするとかなり面倒になったのだが、署名部分は計算から除外するようになった。

だから、非SegwitトランザクションのTXID計算方法と、SegwitトランザクションのTXID計算方法は異なるのだ。


だいたい話は終わりなのだが、余談としてWTXIDのことも書いておこう。

ずばり、WTXIDは、Segwitトランザクションを以前と同じTXID計算方法で求めた値のことだ。
ただ、WTXIDの使いどころが分からないので、計算をしたことがなく、検証まではできていない。
https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki#transaction-id

2017/09/07

[c/c++]JSON-RPCでuint64_tに対応するのは難しいか

最近、サーバ型というかdaemon型というか、バックグラウンドで動くアプリを作っている。
それに対して外部から指示を与えたいことがあるのだが、今までLinuxのメッセージキューを使っていた。
それで困っていなかったのだが、他の類似するツールを見るとJSON-RPCでやりとりしていることが分かった。

長いものに・・・巻かれるしかないのか・・・。

同じ形式でAPIを受け付けるように作っておけば、外側の部分は自分で作らずに済むし、そうしておくことによって他の人から使ってもらえる可能性も上がる(たぶん)。

あきらめて、JSON-RPCのパラメータを受け付けるように改造することにした。


こういうときは、githubなどからライブラリを探して、それを使うのがよいだろう。
Google検索して見つかった一番上が、こちら。

httpの方が汎用性が高いのかもしれないが、TCPのsocketをつくってwrite/read()すれば動くので、作るのが楽そうだ。


半分ほど実装していて思い出したが、今回はuint64_tを使っているのだった。
しかし、この子はintかdoubleしか持っていない。
doubleでは丸められる可能性があって困るのだ。。

そういえば、と別の場所で使っているjanssonも見直してみたが、long long型の対応になっているのでint64_tはいけるものの、uint64_tは無理だろう。

よく考えれば、Cは標準型でそこまでしか対応していないし、JavaみたいにBigDecimalみたいな標準もないため、そもそも対応すること自体が難しいだろう。
janssonのbignum版を作っている人もあったが、整数型はgmpかopensslを使うことになるようだ。
うーん、それはちょっと今回の方針にあわない。。。


今回はintかuint64_tまでしか使わないので、自分でuint64_t対応を追加すればよいのだろうが、気力が湧かない(それでいいのか)。
ひとまず、逃げの手段として、uint64_tは文字列に変換して、読み出すときはまたuint64_tとして戻すことにした。
array型で、順番がこちらで決められるからできる技だ。
ただ、serverもclientも自前じゃないとダメなんだけどね。。。


gccなら__int128があるようで、それならuint64_tのサイズでも収まるから少し気は楽になるが、うーん、やっぱり、なんかねー。
この辺りは、pythonみたいに自由な幅にできる言語が有利ですな。

2017/09/05

[btc]regtestでsegwitするにはブロック数がいる

最近、というわけでもないが、testnetが今ひとつ順調ではないように見える。

数日前は、トランザクションが1つ(というか、coinbaseだけ)のブロックが多く、トランザクションが全然さばけていないようだった。
https://testnet.blockexplorer.com/blocks-date/2017-08-31

今日は普通だと思っていたのだけど、なんかsegwitのトランザクションだけ除外されていないか?
そういう真似ができるのかどうか知らんが、数時間前に発行したsegwitのトランザクションがマイニングされないのに、faucetから送ってもらったトランザクションはすぐにマイニングされていたのだ。


よくわからんが、不安定で作業にならないので、regtestを使うことにした。
初めてのregtestだ。


Bitcoinを使ったアプリケーションのテスト環境 - Develop with pleasure!

bitcoin.confを書き換える程度で動かせた。
regtest時のbitcoin-qtは水色だった。

書いてあるように、bitcoin-cliなどでgenerateコマンドを使うと、その数だけブロックを生成してくれる。
これで、マイニングされたことになるので、ビクビクしなくてよいのだ。


しかし・・・segwitのトランザクションを作ろうとaddwitnessaddressしたのだが、segwitは対応していないとか出てくる。。。
regtestなのに!

検索すると、ちゃんと調べてくれた人が見つかった。
How to activate segwit on regtest

あー、101ブロックしか生成していなかったけど、432ブロック以上ないとsegwitがActiveにならないんだ。
しかし、432ブロックというのはなんだろうか?

https://github.com/bitcoin/bitcoin/blob/28f788e47e58f2b462351d6989348a4e1a241b2b/test/functional/bip68-sequence.py#L371
BIP68関連らしい。

https://github.com/bitcoin/bitcoin/blob/28f788e47e58f2b462351d6989348a4e1a241b2b/test/functional/segwit.py#L198
こちらも432だが、144 * 3ということになっている。

144 = 24(時間) * 60(分) / 10(ブロック毎分)

ということかな?
mainnetの時間で3日分というのが432の根拠のようだ。

なんで3日なのかというのは、わからんかったが、まあいいや。

2017/09/04

[win][修復]Windows10が立ち上がらなくなったので復旧 - 2

まさかの第2弾。
というよりも、OSが立ち上がらないということはしばしばあると思うので、その記録だ。

hiro99ma blog: [win][修復]Windows10が立ち上がらなくなったので復旧


予備で用意しているPCがあり、そのWindows10が起動しなくなった。
用意しているというか、マザーボードやCPUが古くなったので一式買い替えたのだが、その前に使っていたPCだ。
Windowsも新しいPCに持っていこうと思ったのだが、マザーボードが変わるとインストールできないという話を聞いたので、そちらは別途購入したのだ。

最後にWindows Updateしたのが1年くらい前だったので、たぶんその間は起動していないのだと思う。
無事に起動したので、過去のデータはもう不要だろう、とWindowsのリセットで全データ消去を選択。
自動的に再起動してクリーンアップが進んだのだが、途中かどこかでブルースクリーンが発生し、再起動を繰り返すようになってしまったのだ。

クリーンアップしたらきれいな状態で立ち上がるだろう、と思っていたので、修復ディスクは作っていたものの、復旧ディスクは作っていない。
復旧ディスクって、USBメモリ1本使うので、もったいない、と思ったのが正直なところだ。


ブルースクリーンになるのはログイン画面が出る前なのだが、F4を押して起動させるとあのメニューは出てくる。
そこでまたPCのリセットを行ったが、エラーが起きましたというだけで何もできない。
修復ディスクで起動させても、同じようなものだった。

復旧ディスクであれば何でもよいかと思い、ThinkPadで作っていた復旧ディスクで起動したのだが、起動させている間にネットで検索すると、どうも共有できるものではないらしい。
ThinkPadはWin10 Home、予備PCはWin10 Proだったのだが、予備PCにWin10 Homeとかいうパーティションが作られてしまった。。。
もちろん、復旧もできなかった。

このWin10はWin7からのネットワークアップグレードでできているので、Win7のディスクはあるものの、Win10用は何もないのだ。


もうあきらめるしかないかと思ったのだが、もう1つ手段があった。
新しいPC用に買ったWindows10のインストールディスクだ。
これが、使えた。
ディスクから起動すると復旧させるボタンが出てくるのだが、それは押さずに普通のインストールを進める。
プロダクトIDを入力するところをスキップさせると、起動時にネットワーク認証を行うらしい(画面にそう出ていた)。
そうやって進めると、無事に起動できる状態になった。

よかったよかった。
復旧ディスクを急いで作ったのは、言うまでもない。


復旧ディスクって、もうすぐ2017年秋バージョンのリリースが行われるそうなのだが、新しくなるごとに更新した方がよいのだろうか?
そこら辺がよくわからんね。

2017/09/03

[zybo]PetaLinuxでDigilentのチュートリアルが動かん (17)

前回の動かん(16)では、xparameters.hにアドレスの定義が載っていることを確認した。

では、ソースに直接書く方法から、includeして参照する方法に変更しよう。
と書き換えたものの、xparameters.hをincludeしてくれない。。。


xparameters.hは、この2箇所にあるのだが、使うのは前者だ。

components/plnx_workspace/fsbl_bsp/ps7_cortexa9_0/include/xparameters.h
components/plnx_workspace/fsbl_bsp/ps7_cortexa9_0/libsrc/common_v1_00_a/src/xparameters.h


パスを継ぎ足していったのだが、componentsから書いても見つからない。
どこからかの相対パスで指定したいのだが、どこから書いてよいものかもわからん。

あきらめてモジュールのソースファイルと同じ場所にコピーしたのだが、それでもダメだ。
カレントディレクトリすら参照してくれないというのか!


と思ってfindすると、実際にビルドするディレクトリはproject-spec/meta-user/recipes-modules/led8drv/filesではなく、build/tmp/work/plnx_arm-xilinx-linux-gnueabi/led8drv/1.0-r0という場所にファイルをコピーして行っているようだ。
そして、filesにあるファイルをすべてコピーしているわけではなく、xparameters.hなどはコピーされていないため、参照できていない、ということらしい。

じゃあ、何を書き換えたらよいかというと、bbファイルを変更するとコピーしてくれるようだった。

SRC_URI = "file://Makefile \
            file://zybo_gpio.c \
            file://xparameters.h \
            file://xparameters_ps.h \

        file://COPYING \
           "

これで、取りあえずはファイルをコピーしてくれてビルドもできるようにはなった。
だが、ファイルを手動でコピーする手間がかかるし、なにより格好が悪い。


PetaLinux Tools User Guide(UG977 v2014.2)にはpetalinux-configで更新できるようなことが書いてあるのだが、最近ではこのドキュメントは更新していないようだし、やってもダメだった。
きっと、ちゃんとしたやり方があるのだろうとは思うが、わからんのだ。
SDK内であれば何かありそうなのだけど、PetaLinuxのところだけでやりたいのだよなぁ。

2017/09/02

[zybo]PetaLinuxでDigilentのチュートリアルが動かん (16)

久しぶりすぎて、内容を覚えていない・・・。

前回は、GPIOのアドレス定義が自動生成されたxparameters.hに載っていることがわかった、というところまでだった。
何をしていたかというと、Linuxのデバイスドライバを作る際、どのアドレスを操作すればよいのかを調べていたのだ。


今見ているのは、これ。
original: http://www.cqpub.co.jp/interface/download/2016/4/IF1604Z.zip

Interface誌のサンプルをちょっと変更した程度のものだ。
GPIOのアドレスは、gpio_table[]を使っている。

動かん(14)のときにどれを使っているのか計算しているが、mknodしたのが24なのでgpio_table[3]ということだ。
そのアドレスは、0x41200000 + 0x10000 + 0x0。

./components/plnx_workspace/fsbl_bsp/ps7_cortexa9_0/include/xparameters.hを見ると、こういう行があった。

/* Canonical definitions for peripheral BTNS_4BITS */
#define XPAR_GPIO_0_BASEADDR 0x41200000
#define XPAR_GPIO_0_HIGHADDR 0x4120FFFF
#define XPAR_GPIO_0_DEVICE_ID XPAR_BTNS_4BITS_DEVICE_ID
#define XPAR_GPIO_0_INTERRUPT_PRESENT 0

まず、MAP_BASE_ADDRの根拠はわかった。
zybo_gpio.cでは固定値なので、このアドレスも求める方法があるのだろうが、まあ、よかろう。


次はオフセットだ。
制御しているのはZYBOのJEコネクタで、0x41210000から1KBをioremap()し、32bitを書込むようにしている。

ああ、こういう定義が近くにあった。

/* Definitions for peripheral LEDS_4BITS */
#define XPAR_LEDS_4BITS_BASEADDR 0x41210000
#define XPAR_LEDS_4BITS_HIGHADDR 0x4121FFFF
#define XPAR_LEDS_4BITS_DEVICE_ID 1
#define XPAR_LEDS_4BITS_INTERRUPT_PRESENT 0
#define XPAR_LEDS_4BITS_IS_DUAL 0

Block Designを見ると、GPIO類はこうなっていた。

image

この名前が、そのままマクロ定義になるのか。


mknodするminor番号だが、zybo_gpio.cではビットを表していたのか。

0- 7 : ボタン
8-15 : DIPスイッチ
16-23 : 未割り当て
24-31 : LED

だから、16~23だとエラーなのか。
ビットシフトを3つやってるのも、8bit単位で何番目かを割り出すという意味なのだろう。
読み書きの方向についてはminorのb4を使っているが、0~15はINPUTだから使っただけか。
LEDでもスイッチでもいけるように、GPIO_BUFFという構造体を用意して、そこに情報を突っ込み、あとはシステムコールで呼び出されたらそれを使うだけ、ということにしたかったのだろう。


ioremap()は、物理メモリをアクセスする準備みたいなもののようだ。
IoMemoryAccess - Kernel Newbies Japan
MMUもあるし、こういうやり方になるのか。
戻り値をそのまま使ってよいわけではなく、readb/w/l()、writeb/w/l()を介してアクセスするそうだ。
zybo_gpio.cでは iowrite32()を使っているので、ビット幅で指定するタイプもあるのか。

9.4. Using I/O Memory
こちらはオライリーのLinux Deveice Drivers第3版の元ページ?のようだが、readb()などのタイプはolderと書いてある。
まあ、ビット幅の方がわかりやすいわね。


ioremap()だが、終わったらiounmap()しなくてよいのだろうか?
なんとなく、close()時にやった方が良い気がする。

Linuxデバイスドライバのお作法がわかっていないので、基本的なところは抑えた方がよさそうだ。

[c++]Boostのdijkstra_shortest_paths() - end

Boostのグラフで経路を求めたので、最後に、自分であれこれやったソースをGistに置いておこう。

boostのグラフを使って経路探索するサンプル


経路は、boost.jpのグラフにあるものを使った。

$ g++ -o tst dijk_dist.cpp
$ ./tst
distance: 11
START --> Asia --> Beer --> Devel --> Foobar --> GOAL


Boostのサンプルにあった、graphvizで出力するやりかたも真似した。

image

双方向にしたのでゴチャゴチャしているが、方向によって重みが違う場合にはこうやることになるだろう(今回は同じ重みだが)。

[c++]Boostのdijkstra_shortest_paths() - 4

前回は、dijkstra_shortest_paths()に重みを指定しつつ、経路を得るための引数を指定するところまでだった。
なんであんな中途半端で終わらせたかというと、仕事に行く時間だっただけだ。。。

動作結果は、OKだった。
検証したソースを載せたいところだが、そっちは仕事で書いているコードでやってしまったのだ。すまん。


第3引数には他の種類もある。
こちらでは、visitor()というものを使っている。
Boost.Graphに入門 - Faith and Brave - C++で遊ぼう
やっていることは同じような内容なのだが、最短経路以外にも試されている。


BoostのGraphは自由度が高いので、あれこれできてしまい、検索して見たサイトで全部やり方が違っていて「うーん、難しい・・・」と感じてしまう。

ただ、便利だし、Cから使うときもそこだけライブラリにしておけばうまいことやれるんじゃなかろうかと思う。
Makefileで、CとC++を混在させるやり方がよくわからんのだ。。。
.oを.cやら.cppに見立てる方式ではダメだから、最近はソースファイル名を列挙する方式にしているのだけど、extern "C"だけでうまく回避できるんだっけ?


いかんいかん、話が逸れてしまった。
ともかく、BoostのGraphは、大ざっぱに言えば、

  • adjacency_list<>でグラフを構成する型を作る
  • そのインスタンスを作って、vertexやedgeを突っ込んでいく
  • アルゴリズムを実行
  • 結果を得る

という流れのようだ。

そして、vertexやedgeは単純なものであれば元からある型を使えばよいし、プロパティとして複数の情報を持たせたければ構造体などを指定すればよい。
プロパティを自前で用意する場合は、重みをweight_map()で指定する。
距離の結果を得たい場合はdistance_map()を、経路の結果を得たい場合はpredecessor_map()を指定する。

私が使う範囲では、このくらいわかっておけばよさそうだ。

2017/09/01

[c++]Boostのdijkstra_shortest_paths() - 3

第3回。前回はこちら


前回は、グラフの有向や無向の設定だけを見た。
それ以外にグラフの設定で使いそうなのが、プロパティだろう。
経路探索する場合は、vertexとvertexのつながりだけでなく、経路の取捨選択に用いる情報を付加することが多いからだ。
よくあるのは、距離とか、そこを通るのにかかる費用とか。

距離のような単純な情報であればboostが用意していて、edgeのプロパティとして

boost::property<boost::edge_weight_t, int>

などと書いてあげればよい(これはint型の重み)。


ただ、重みの情報は1つだけど、そのルートを通るようになった場合に参照したくなる情報もある。
さっきの例でいえば、重みとしては距離を使うけれども、経路が分かった後には通行料を知りたい、などという場合だ。
そういうときは、自分でプロパティを設定できるようである。


https://boostjp.github.io/tips/graph.html#bundle-property
ここでは、structを作ってプロパティにしている。
何でもいいのかな?
まあ、C++のtemplateはマクロみたいなものだったと思うので、ちょっと種類が異なるグラフ型を作ると、それに関連する関数も新たに作ることになってしまうのだと思うが。

試して分かったが、このプロパティにする型だが、関数内に書いてはダメだった。
グローバルスコープじゃないと展開できないのだろう(私はC++にあまり詳しくないので、推測だ)。


あとは真似をしておけばdijkstraで経路探索したり、距離を表示させたりすることはできた。
しかし、サンプルではせっかくedgeにもプロパティを付けてTokyoやNagoyaを設定しているのに、表示するときには固定文字列を使っている。
かといって、map[v1].nameなどと指定するだけでは芸が無い気もする。

それに、これは2点間だからよいが、複数のvertexがあって経路探索した場合は、どの経路を通ったかをもらって、そこからプロパティを取得していきたいではないか。


https://boostjp.github.io/tips/graph.html#dijkstra-shortest-paths
経路探索して、その経路を出力するサンプルがこちらだ。
プロパティはedgeだけで、int型になっている。
そして経路出力しているところを見ると、parentという変数を使っている。
使われ方は・・・ああ、プロパティサンプルのdistanceと同じ立ち位置なのか。

ただ、プロパティのサンプルではboost::weight_map()を使っているが、ここではboost::predecessor_map()を使っている。
dijkstra_shortest_paths - boostjp
weight_map()はINで、predecessor_map()はOUTだ。
INなのに、なぜ・・・。

あ、dijkstra_shortest_paths()が長いので気がつかなかったが、引数は3つしかないんだ。
そして、第3引数はxxx_map()がドットでつながっている。


Boost Graph Library: Dijkstra's Shortest Paths - 1.65.0

引数が3つのタイプは、これだ。

// named parameter version
template <
         typename Graph,
         typename P,
         typename T,
         typename R>
void dijkstra_shortest_paths(
         Graph& g,
         typename graph_traits<Graph>::vertex_descriptor s,
         const bgl_named_params<P, T, R>& params
);

最後のparamsが、xxx_map()が連鎖しているところになる。
引数が多いタイプも合って、そっちはnon-named parameter versionと呼ばれている。
あまり読んでないが、ここに書いてあるxxx_map()をどんどんつないでいって、指定したいものだけ指定すれば応じた結果が得られるということだろう。


プロパティのサンプルは、こう。

weight_map().distance_map()

経路を求めるサンプルは、こう。

predecessor_map().distance_map()

プロパティのサンプルは重みを別のところから取ってくるからweight_map()を使っているのだろうか。
しかし、それならプロパティにHighwayを指定しなくてもなんとかなるんじゃ無かろうか、と思ったが、それはコンパイルエラーになった。
ではweight_map()だけ外したらどうなるかと思ったら、それはdistance_map()がわからんと言われた。
distance_map()は「UTIL/OUT」になっているから、オプション扱いで、何かの後ろに付けるということか。


weightは任意のプロパティから指定したい、経路の情報は欲しい、ということであれば、こんな感じにするとよいのか。

    std::vector::vertex_descriptor> pred(num_vertices(map));
    std::vector distance(boost::num_vertices(map));
    boost::dijkstra_shortest_paths(map, v1,
            boost::weight_map(boost::get(&Highway::distance, map)).
            predecessor_map(&pred[0]).
            distance_map(&distance[0]));


検証は、次回だ。

[c++]Boostのdijkstra_shortest_paths() - 2

意外なことに、2回目です。
前回はこちら


グラフ - boostjp
このサイトを見て、探索はできるようになったのだが、あまりにも理解できなさすぎて、応用がまったくできない。
理論はもうあきらめるとして(いいのか。。。)、主な使い方くらいは覚えよう。


ツリーではなく、グラフだ。
だから、ノードやブランチではなく、vertexやedgeと呼ぶようだ。
まあ、ツリーでもedgeを使ったりするようなので、そこまで依存した言葉遣いではないのだろう。


このグラフ全体をclass adjacency_listが持つようだ。
派生して使うのではなく、templateになっていて、テンプレートパラメータを指定することでグラフ全体の設定になるようだ。

説明はサイトを読んだ方が早いだろう。
主に変更しそうなものは、グラフの有向(一方向、双方向)/無向と、カスタムプロパティかな。
双方向有向が無向と違うのは、重みが方向によって替えられたり、辺によって一方向にすることができる、というところか。
細かいけど、片方向はdirectedS、無向はundirectedSだけど、双方向はbidirectionalSと末尾が違うので注意だ。


こんな感じで、じわじわ読み進めていこう。

主な使い方、と最初に書いたものの、それですらいつ終わるかわからんが、やらねば終わらぬのだ。