Crystal言語には、C言語のライブラリのバインディングを自動生成するツールが存在する。
追記:これをさらにラップした libgen というものがあるそうです。この記事ではlibgenは扱いません。
crystal_lib の使い方は簡単で、
git clone https://github.com/crystal-lang/crystal_lib
cd crystal_lib
shards install
crystal build src/main.cr
として実行形式のファイルを作成する。
次に、examplesを参考にして作成したいライブラリのテンプレートを作る。いくつかexampleを貼ります。こんな感じ。
lib_event.cr
@[Include("event.h", prefix: %w(event_ EVENT_ Event))]
@[Link("event")]
lib LibEvent
end
lib_git2.cr
@[Include(
"git2.h",
prefix: %w(git_ GIT_ Git),
import_docstrings: "brief",
)]
@[Link("git2")]
lib LibGit2
end
lib_ruby.cr
@[Include(
"ruby/st.h",
"ruby/ruby.h",
prefix: %w(rb_ ruby_),
remove_prefix: false,
)]
@[Link("ruby")]
lib LibRuby
end
prefixの指定ができるが、それ以外に自分でfunctionを記述することもできるようだ。
libc.cr
@[Include(
"stdlib.h",
"sys/types.h",
"sys/socket.h",
"netinet/tcp.h",
"arpa/inet.h",
"netdb.h",
"string.h",
"stdio.h",
"unistd.h",
"sys/file.h",
"dirent.h",
"sys/stat.h",
"glob.h",
flags: "-Dlint",
)]
lib LibC
AF_UNSPEC = AF_UNSPEC
AF_UNIX = AF_UNIX
AF_INET = AF_INET
AF_INET6 = AF_INET6
SOL_SOCKET = SOL_SOCKET
SO_REUSEADDR = SO_REUSEADDR
SO_KEEPALIVE = SO_KEEPALIVE
SO_LINGER = SO_LINGER
SO_SNDBUF = SO_SNDBUF
SO_RCVBUF = SO_RCVBUF
TCP_NODELAY = TCP_KEEPALIVE
TCP_KEEPIDLE = TCP_KEEPALIVE
TCP_KEEPINTVL = TCP_KEEPINTVL
TCP_KEEPCNT = TCP_KEEPCNT
# memory
fun malloc
fun free
# socket
fun freeaddrinfo
fun gai_strerror
fun getaddrinfo
fun socket
fun socketpair
fun inet_pton
fun inet_ntop
fun htons
fun bind
fun listen
fun accept
fun connect
fun gethostbyname
fun getsockname
fun getpeername
fun getsockopt
fun setsockopt
fun shutdown
# string
fun atof
fun strtof
fun strlen
fun snprintf
# file
F_OK = F_OK
X_OK = X_OK
W_OK = W_OK
R_OK = R_OK
fun access
fun link
fun rename
fun symlink
fun unlink
fun flock
# dir
fun getcwd
fun chdir
fun opendir
fun closedir
fun mkdir
fun rmdir
fun readdir
fun rewinddir
fun glob
fun globfree
# env
# $environ : Void
fun getenv
fun setenv
fun unsetenv
end
テンプレートを作成し終わったら、先程生成した実行形式のファイルで読み込む。アウトプットは標準出力なので適宜保存する。
./main examples/lib_git2.cr > libgit2.cr
このバインディング自動生成機能だが、当然完璧ではない。
私の観測した範囲では
- bitfields はうまく変換されない
- alias と type を複数回定義する
のようなことがあった。細かい欠点はともあれ、Crystal言語製作者謹製のライブラリであり、非常に便利であることは間違いないと思います。
この記事は以上です。