2016年8月16日火曜日

windows10 アニバーサリーUpdateでbashを試してみる

ちょいと勇気がいりましたが、windows10でanniversary updateを行い(通知が来ないので手動でやりました)、bash on windowsを試してみました。

やり方は各種サイトにありますので割愛しますが、とにかく再起動が多い!なんか懐かしい風景です。(昔はシステム更新なんかだと、こんなんばっかだった)さて肝心の"bash on windows"ですが、なんというかvirtual boxでubuntuが動いているような感じです。それとも、今はやりのコンテナに仕立ててきたのか?そんなに重くはないんですが、問題は文字コードが…
何書いてあるのかわかりません。対策をあちこち知らべましたが、どうも決め手がないようです。まだマシンによって差がでてしまうようです。

ただそれ以外は普通にubuntuが動いています!いや、これは素晴らしい。これができると、これまでプログラム作るとき、macに逃げていたのが、windowsでもやってみるか、という気になります。(それが狙いだという話もありますし)

しかし、GUIはどうするんだろう?APIが全く違うし、windowsのGUI関係のAPIの一部でもこのシステムに取り込むのは大騒ぎになるだろうし。web系のサーバに使ってくれないかな、というM$の考えなんだろうけど、まだTCP/IPのAPIが完全には機能していないらしいし、今後どうなるのかな。(個人的にはCygwinが嫌いなんで、ある程度残って欲しいんですが、かなり今の状況では怪しいです。何か使い道を考えてあげないと)
ただ無理にGUIのAPIを移植しなくてもいいと思います。今、時代はwebですべてすますのが本流なんで、GUIはブラウザにまかせてしまえばいいですから。難しいのは不安定なwindows OSの上で如何に安定して動く環境にできるかですが、こればっかりはかなり難しいかな。

PS
どうもanniversary updateにしたのは早まったようです。ファイルの移動とかでおかしな挙動が見られます。
あと肝心のbashですがどうにも日本語が表示できないので、以下の設定で動かしています。

$ LANG=en_US.UTF-8

要は英語表記でアラートとか出してね、ですね。あと、一体どういう環境になっているのかわからないのですが、コンテナでもないようで、ping、ifconfig等のネットワーク系のコマンドが実行できません。ベータ版とは聞いていますが、どんな実装になってるんだ???

2016年8月12日金曜日

SQLite3のプログラムの勉強

ちょっとSQLite3を使ったプログラムをWindowsで作るとどうなるのか調べてみたくなりました。ただ私は普段LinuxかMacでプログラムを作ることが圧倒的に多いので、まずは慣れたMac、Xcodeで作ってみます。

1. sqlite3のインストール
brewを使ってインストールしています。コマンドラインでも使えますし、ヘッダ、ライブラリも一緒にインストールしてくれます。

2. プログラムの作成
とりあえず、以下の様なプログラムを作ってみました。
//
// main.cpp
// SQLiteTest
//
// Created by hiro on 2016/08/11.
// Copyright © 2016年 hiro.maeda. All rights reserved.
//
#include <stdlib.h>
#include <iostream>
#include <sqlite3.h>
int main(int argc, const char * argv[]) {
// dbファイルを指定した場所に作るための確認用コード
std::string home = getenv("HOME");
std::cout << "$HOME = " << home << std::endl;
home += "/ProgWork/SQLite";
std::cout << "$HOME = " << home << std::endl;
// ここから本体
std::string dbfile = home + "/test.db"; // DBファイル
sqlite3* db = NULL;
// dbのオープン
int err = sqlite3_open(dbfile.c_str(), &db);
if (err != SQLITE_OK)
{
// dbファイルオープン失敗
std::cout << "OPEN ERROR " << err << std::endl;
exit(-1);
}
std::cout << "OPEN SUCCESS!" << std::endl;
// SQLの実行(insert)
char* errCode = NULL;
err = sqlite3_exec(db, "insert into tbl_test(id, name) values('123', 'hoge');", NULL, NULL, &errCode);
if (err != SQLITE_OK)
{
// SQL実行失敗
std::cout << "INSERT ERROR " << err << ":" << errCode << std::endl;
err = sqlite3_close(db);
exit(-1);
}
// SQLの実行(select)
sqlite3_stmt* pStmt = NULL;
// データの抽出、ステートメントの用意
err = sqlite3_prepare_v2(db, "select * FROM tbl_test where id=123", 64, &pStmt, NULL);
if (err != SQLITE_OK)
{
// SQL実行失敗
std::cout << "SELECT ERROR " << err << std::endl;
err = sqlite3_close(db);
exit(-1);
}
else
{
// データの抽出
while (SQLITE_ROW == (err = sqlite3_step(pStmt)))
{
int id = sqlite3_column_int(pStmt, 0);
const unsigned char* name = sqlite3_column_text(pStmt, 1);
std::cout << "id: " << id << ", name: " << name << std::endl;
}
if (err != SQLITE_DONE)
{
std::cout << "SELECT DONE ERR" << std::endl;
err = sqlite3_close(db);
exit(-1);
}
}
// ステートメントの解放
sqlite3_finalize(pStmt);
// dbのクローズ
err = sqlite3_close(db);
if (err != SQLITE_OK)
{
// dbファイルクローズ失敗
std::cout << "CLOSE ERROR " << err << std::endl;
exit(-1);
}
std::cout << "CLOSE SUCCESS!" << std::endl;
return 0;
}

とてもシンプルです。実行結果は以下の様になります。

$HOME = /Users/hogehoge
$HOME = /Users/hogehoge/ProgWork/SQLite
OPEN SUCCESS!
id: 123, name: hoge
CLOSE SUCCESS!

createがありませんが、そこはマニュアルで作っています。(プログラムに書いてもいいんですが、毎回実行するためにいちいちdbファイルを削除するのも面倒なので。)

> create table tbl_test(id integer primary key, name text);

最終的にはinsertのところをupdateに変えて、プロセス間の通信代わりに使おうと目論んでいます。

3. 注意点

  • Xcodeの設定でライブラリの追加オプション"-lsqlite"を忘れない様に。
  • 単純にやろうと思うなら、sqlite_open(), sqlite_close(), sqlite_exec()だけで済ますこともできます。ただselect文をsqlite_exec()でやろうとすると、どうしても出力をcallbackで受けないといけなくなります。callback関数を書くのが面倒だったので、非同期クエリで実装しています。(こちらも面倒だがやむを得ません)
  • sqliteはsql文の実行ではデフォルトでオートトランザクションになっています。将来的にプロセス間の通信に使うつもりなら本当は、"bgein","commit"と明確にトランザクションの指定をしてやるべきです。ただそんな複雑な通信は当面する気がなく、一方向だけ(片方がwriteして、他方はreadするだけ)のつもりなので、当面はこれでも問題はありません。
さて、これをwindowsのVisualStudioのc++で実装です。2015ではUWPアプリ(Universal Windows Platform)として、SDKにsqlite3が標準で入っているらしいです。実装もこのままでコンパイルが通りましたが、リンクでどうしてもsqlite関係の関数が「未解決の外部シンボル」と言われてしまいます。(ちゃんとwinsqlite3.libを追加のライブラリに指定しているんですが・・・)ちょいとこの問題の解決には時間がかかっています。