2010/06/18

Recent entries from same category

  1. VimConf 2023 Tiny に参加しました
  2. Vim で Go 言語を書くために行った引越し作業 2020年度版
  3. Vim をモダンな IDE に変える LSP の設定
  4. ぼくがかんがえたさいきょうの Vim のこうせい 2019年 年末版
  5. VimConf 2019 を終えて

tyruさんが既に記事にしてくれてますが、こちらでも。
mattnさんが前の記事にコードで回答してくれた - おつあり

mattnさんが前の記事にコードで回答してくれた Vim mattn’s libcallex-vim at master - GitHub こんなリポジトリが作られたので十中八九僕のlibcall()...

http://d.hatena.ne.jp/tyru/20100518/cool_mattn
通常 libcall は引数が1つしか扱えないのですが、内部でJSONでやりとりしてC言語で書いた呼び出しproxyを介して外部ライブラリ(DLL等)の関数を呼び出せます。
とはいってもvimで扱える型しか対応していませんが、ちょっと無茶すればいろんな事が出来ます。
例えばuser32.dllのMessageBoxAを実行したり... so ../libcallex.vim

silent unlet! lib

let lib = libcallex.load('msvcrt.dll')
let username = lib.call('getenv', ["USERNAME"], 'string')
call libcallex.free(lib)

let lib = libcallex.load("user32.dll")
if lib.call('MessageBoxA', [0, "Hello ".username."\r\nCan you see this message?", 'Hello World', 4]) == 6
  call lib.call('MessageBoxA', [0, 'You clicked "YES"', 'Hello World', 0])
else
  call lib.call('MessageBoxA', [0, 'You clicked "NO". Are you all right?', 'Hello World', 0])
endif
call libcallex.free(lib)
バッファを引数に取る関数を呼び出してWindowsのSystemディレクトリを取得したり... so ../libcallex.vim

silent unlet! lib

let lib = libcallex.load('kernel32.dll')

let buf = repeat(' ', 255)
let args = [buf, 255]
call lib.call('GetWindowsDirectoryA', args, 'number')
let dir = args[0]
echo "your windows directory: " . dir

let buf = repeat(' ', 255)
let args = [buf, 255]
call lib.call('GetSystemDirectoryA', args, 'number')
let dir = args[0]
echo "your system directory : " . dir

call libcallex.free(lib)
無理やりlongのポインタ作ってバッファ書き込み数を参照渡しで扱う関数を呼び出したり... so ../libcallex.vim

silent unlet! msvcrt
silent unlet! advapi32

let msvcrt = libcallex.load('msvcrt.dll')
let advapi32 = libcallex.load('advapi32.dll')

" make address of variable which is stored 256
let ptr = float2nr(eval(msvcrt.call('malloc', [4], 'number')))
call msvcrt.call('memset', [ptr, 0, 4], 'number')
call msvcrt.call('memset', [ptr+1, 1, 1], 'number')

let buf = repeat(' ', 256)
let args = [buf, ptr]
call advapi32.call('GetUserNameA', args, 'number')
let username = args[0]

call msvcrt.call('free', [ptr], 'number')

call libcallex.free(advapi32)
call libcallex.free(msvcrt)

echo username
出来ます。(まぁ最後のはやりすぎとして)
分かる人は想像通りですが、簡単なインラインアセンブラで実現してます。
いままでvimからDLL呼び出しが出来ないと悩んでおられた方には有用かもしれません。

えっ?mattnとtyruさんだけだって?
Posted at by