libcall (or libcallnr) は、動的ライブラリの関数を呼び出すことができる。
ここでは以下について述べる。
- vim scriptからlibcallで動的ライブラリを呼び出す方法
- libcallで呼ぶことのできる動的ライブラリの作成方法
vim scriptからlibcallで動的ライブラリを呼び出す
libcallから呼び出すことのできる動的ライブラリ内の関数シグニチャは、
- {char*,int} cdecl hoge({char*,int})
でなければならない。
libcallを実際に使う際には、
" char* cdecl some_func(char*)を呼び出す場合
" *nix系の場合 => 拡張子まで含めたファイルパスを指定
echo libcall('path/to/shared-object.so', 'some_func', 'string to be passed')
" windowsの場合 => 拡張子を含めないファイルパスを指定
echo libcall('path/to/dynamic-link-library', 'some_func', 'string to be passed')
とする。
libcallの第一引数には動的ライブラリのファイルパスを指定、第二引数には呼び出す関数名を指定する。
第三引数には、文字列か整数を渡す必要がある。
libcallとlibcallnrの使い分けとしては、呼び出す関数の返り値がchar*かintかで分ける。
libcallで呼ぶことのできる動的ライブラリの作成方法
関数宣言時の注意点は以下。
- 呼び出し規約はcdeclを使用する
- 引数は厳密に1つのみ、以下の型で受け取る
- char*
- int
- 返り値は以下の型のみ使用できる
- char*
- int
返り値としてchar*を使用する場合、vim側でfreeは行われないため、動的ライブラリ側でfreeする必要がある。
また通常の動的ライブラリと同様、動的ライブラリ内でデータを保持することができる。
ただし動的ライブラリ側でdlopen()し、自分自身をロードしなければならない。これについては次節で。
shared objectの場合は、コンパイルオプションに-fPICを指定する必要がある。
dynamic link libraryの場合は、__declspec(dllexport)する必要がある。
動的ライブラリ内でデータを保持する方法
動的ライブラリ内でデータを保持する場合、
-
*nix系
dlopen()で自身をロードし、終了時にdlclose()する必要がある。
-
windows系
LoadLibrary()で自身をロードし、終了時にFreeLibraryする必要がある。
このように、自身をロードしておかないと、libcall()での呼び出しごとに動的ライブラリの初期化と破棄を
繰り返すことになる。