Humanity

Edit the world by your favorite way

libcall()で引数が2個以上のC関数を呼び出す

libcall()という関数を使うとC関数をVimスクリプト側から呼び出せます。
しかしこの関数はC関数に「0個あるいは1個」しか引数を渡すことができません。


最近僕がよくコミットをしているリポジトリsyslib.vimというものがあります。
これはlibcall()を使ってVimに足りないと思われるシステム系関数*1を実現するものです。

そこで、syslib.vimに2個以上の引数を渡せるlibcall()を実装すればいいのではないか。
そんなことをふと思いついて今日*2実装の参考としてVimのソースを読んでlibcall()の実装を調べてみた。
その格闘の記録の詳細は
Twilog
を読んでもらうとして、要約だけ書いておきます。

要約

結論: libcall()の第3引数がListでも受け付けるようにする件のC実装は現実的でない。syslibとかvimprocみたく一つの引数にまとめて渡してC,Vimスクリプトで相互変換するのが(多分)ベター。#vim

http://twitter.com/tyru/status/14171440192

なぜかと言うと、引数を2個以上取るとなると「その要素分*2(要素の文字列型、整数型)*2(返り値の文字列型、整数型)」*3だけ関数呼び出しのためのコードを用意しなきゃならない。
これは現実的ではないというか非常に面倒くさい。
またPerl*4などはperl*5でCコードなどを生成といったことが結構行われてたりするのだけど、
現状のVimリポジトリを見ると新たにビルドのアレコレを、よりによって1つのパッチのためにいじくるのも現実的ではない。

...と思ったけど

このエントリを書いてる途中に、自動生成したコードをパッチとして追加すればいいんじゃ?という至極単純な発想に至りました。
だいたい引数が20個ぐらいまでのコードを生成すればいいと思った。
つまり20*2*2=80通り。


まぁ、生成するのはVimのマクロとかでもできるんだけど、問題はメンテナンスなんじゃないか。
と、思ったけどこれもそうそう変更する箇所かと言われるとそうでもない。

fmfm

暇があったらsyslib.vimで2個以上呼べるlibcall()を実装してみるかも。
あとそこまでするんだったらついでにVimのパッチも書いてみたい。

*1:rmdir()など

*2:12時過ぎてるけど

*3:http://twitter.com/tyru/status/14169712940 http://twitter.com/tyru/status/14170416798

*4:に限らずrakudo,parrotなど

*5:大文字のPerlPerlのことを指し、小文字でperlと書くと実行形式の/usr/bin/perl(かどうかは知らないけど)を指す