2016/05/30

Recent entries from same category

  1. RapidJSON や simdjson よりも速いC言語から使えるJSONライブラリ「yyjson」
  2. コメントも扱える高機能な C++ 向け JSON パーサ「jsoncpp」
  3. C++ で flask ライクなウェブサーバ「clask」書いた。
  4. C++ 用 SQLite3 ORM 「sqlite_orm」が便利。
  5. zsh で PATH に相対パスを含んだ場合にコマンドが補完できないのは意図的かどうか。

C言語とか C++ でマイクロフレームワークとか聞くと鼓動の高鳴りを抑えられなくなるmattnですこんにちわ。

Balde — A microframework for C based on GLib and bad intentions.

Features Simple templating engine, that converts markup to C code that is linked directly to the app...

https://balde.rgm.io/

2016年に glib で Web だと?と言われそうな気がしなくないですが面白そうな物を見つけました。特徴は

  • 簡単なテンプレートエンジンを提供し、マークアップからC言語のコードへ変換されアプリケーションのバイナリに直接埋め込まれる。
  • 静的リソースはアプリケーションのバイナリに埋め込まれサーブされる。
  • RESTful なリクエストのディスパッチを行い、ほぼ全ての HTTP メソッドをサポート。
  • URL の逆引き。 (Flask の "url_for" 関数に似ている)
  • セキュアクッキー(クライアントサイドセッション)
  • ファイルのアップロード
  • SCGI や CGI サーバとの親和性
  • GLib が稼働するあらゆるシステムで稼働する

まずは簡単なアプリケーションから。

#include <balde.h>

balde_response_t*
hello(balde_app_t *app, balde_request_t *request) {
  return balde_make_response("Hello World! I'm the balde! :D");
}

int
main(int argc, char *argv[]) {
  balde_app_t *app = balde_app_init();
  balde_app_add_url_rule(app, "hello""/", BALDE_HTTP_GET, hello);
  balde_app_run(app, argc, argv);
  balde_app_free(app);
  return 0;
}

pkg-config が提供されるのでコンパイルも楽ちん。

$ gcc -o app `pkg-config --cflags balde` main.c `pkg-config --libs balde`

静的ファイルを扱うには少し癖があり、定義ファイルからリソースとしてコンパイルする必要があります。

<?xml version="1.0" encoding="UTF-8"?>
<gresources>
    <gresource prefix="/static">
        <file>foo.js</file>
        <file>foo.css</file>
        <file>asd/bola.txt</file>
    </gresource>
</gresources>

もちろんこの XML と同様に static/foo.js, static/foo.css, static/asd/bola.txt が置かれているとします。リソースの生成方法は以下の通り。

$ glib-compile-resources --generate --sourcedir static --target static-resources.c static-resources.xml

ソースファイルは以下の様にルーティングを変更します。

#include <balde.h>
#include "static-resources.h"

balde_response_t*
hello(balde_app_t *app, balde_request_t *request) {
  return balde_make_response("Hello World! I'm the balde! :D");
}

int
main(int argc, char *argv[]) {
  balde_app_t *app = balde_app_init();
  balde_resources_load(app, static_resources_get_resource());
  balde_app_add_url_rule(app, "hello""/", BALDE_HTTP_GET, hello);
  balde_app_run(app, argc, argv);
  balde_app_free(app);
  return 0;
}

そしてコンパイル

$ gcc -o app `pkg-config --cflags balde` main.c static-resources.c `pkg-config --libs balde`

テンプレートを使う場合は専用ツールを利用します。templates/hello.html というファイルを用意します。

<h1>Hello, {{ name }}!</h1>

コマンドラインから balde-template-gen コマンドを実行します。

$ balde-template-gen templates/hello.html templates/hello.h
$ balde-template-gen templates/hello.html templates/hello.c

ソースコードを修正します。

#include <balde.h>
#include "static-resources.h"
#include "templates/hello.h"

balde_response_t*
hello(balde_app_t *app, balde_request_t *request) {
  balde_response_t *response = balde_make_response("");
  const gchar *name = balde_request_get_arg(request, "name");
  balde_response_set_tmpl_var(response, "name", name != NULL ? name : "World");
  balde_template_hello(app, request, response);
  return response;
}

int
main(int argc, char *argv[]) {
  balde_app_t *app = balde_app_init();
  balde_resources_load(app, static_resources_get_resource());
  balde_app_add_url_rule(app, "hello""/", BALDE_HTTP_GET, hello);
  balde_app_run(app, argc, argv);
  balde_app_free(app);
  return 0;
}

そしてコンパイル。

$ gcc -o app `pkg-config --cflags balde` main.c static-resources.c templates/hello.c `pkg-config --libs balde`

出来上がったアプリケーションに -s オプションを付けるとスタンドアローンサーバとして起動します。ブラウザから http://localhost:8080/?name=mattn の様なURLを開くとちゃんと動作しているのが分かるかと思います。尚、msys2 でビルドして見ましたが問題なく動作しています。glib がインストールされている同じOS同士ならばバイナリ1つでデプロイが完了します。便利そうですね。

LGPL 2.1 のライセンスのもと利用出来ます。

Posted at by