w32apis.rb
ちょっと改造。
require 'Win32API' class W32APIs attr_reader :apis attr_accessor :incpath include Enumerable @@h = { 'int'=>'I', #..snip.. 'WCHAR'=>'H', } def each(&block) @apis.each{|k,v| yield k,v} end def initialize(incs={'winuser.h'=>'user32'},incpath=['/usr/include/w32api']) @apis = { } @incpath = incpath add_apis(incs) end def add_apis(incs) incs.each do |inc, dll| path = @incpath.find{|p|File.exist?(p+'/'+inc)} open(path + '/' + inc) do |f| f.each do |l| if /^(\w.+)\((.+)\)\s*;\s*$/ =~ l ret, arg = $1, $2 next if /^typedef/ =~ ret ret.gsub!(/WIN[A-Z]*APIV?(\W)/){$1} ret.sub!(/^\s*(.+)\s*$/){$1} ret.sub!(/^extern\s*/,'') next if 'DECLARE_HANDLE' == ret rets = ret.split args = arg.split(/\s*,\s*/) arg_str = '' args.each do |e| e.gsub!(/^const/i,'') e.sub!(/^\s+/,'') e.sub!(/\s+\w+$/,'') unless @@h.key?(e) if /\s*\*\s*$/ =~ e @@h[e] = 'P' #FixMe elsif /^LP/ =~ e @@h[e] = 'P' #FixMe else @@h[e] = '-' end end arg_str << @@h[e] end @apis[rets[1]] = [nil, dll, arg_str, @@h[rets[0]], l] end end end end end def method_missing(name, *arg) n = name.to_s a = @apis[n] unless a[0] a[0] = Win32API.new(a[1], n, a[2], a[3]) end a[0].call(*arg) end end if $0 == __FILE__ w = W32APIs.new w.MessageBoxA(0, "Hello, World!", "Title", 0) end
使い方。
【新規作成/APIグループの追加】
w = W32APIs.new
w.add_apis('rapi.h'=>'rapi.dll')
(デフォルトでは user32.dll に入っている api しかサーチしてない)
【APIのコール】
w.MessageBoxA(0, "Hellow, World!", "Title", 0)
#初めて↑コールされた時点でmethod_missingで Win32API.new されて定義される
【EnumerableでAPIを探す】
apis = w.select{|k,v|/MessageBox/=~k/}
api = w.find{|k,v|/MessageBox/=~k}
【その他】
irbとか使ってて、ちょっと win32api の検索をしたり、引数を調べたり、動作確認をしたりとかしたい時とか便利。
irb(z:/ara/):004:0> require 'w32apis';w = W32APIs.new;1 R:1 irb(z:/ara/):005:0> w.add_apis('rapi.h'=>'rapi.dll') R:{"rapi.h"=>"rapi.dll"} irb(z:/ara/):006:0> w.select{|k,v|/CeG/=~k} R:[["CeGetFileTime", [nil, "rapi.dll", "PPPP", nil, "STDAPI_(BOOL) CeGetFileTime (HANDLE, LPFILETIME, LPFILETIME, LPFILETIME); \n"]], ["CeGetLastError", [nil, "rapi.dll", "V", nil, "STDAPI_(DWORD) CeGetLastError (void);\n"]]] irb(z:/ara/):007:0> w.select{|k,v|/MoveW/=~k} R:[["MoveWindow", [nil, "user32", "LIIIIL", "L", "WINUSERAPI BOOL WINAPI MoveWindow(HWND,int,int,int,int,BOOL);\n"]]] irb(z:/ara/):008:0> w.select{|k,v|/MessageBox/=~k} R:[["MessageBoxA", [nil, "user32", "LPPL", "I", "WINUSERAPI int WINAPI MessageBoxA(HWND,LPCSTR,LPCSTR,UINT);\n"]], ["MessageBoxExA", [nil, "user32", "LPPLH", "I", "WINUSERAPI int WINAPI MessageBoxExA(HWND,LPCSTR,LPCSTR,UINT,WORD);\n"]], ["MessageBoxW", [nil, "user32", "LPPL", "I", "WINUSERAPI int WINAPI MessageBoxW(HWND,LPCWSTR,LPCWSTR,UINT);\n"]], ["MessageBoxExW", [nil, "user32", "LPPLH", "I", "WINUSERAPI int WINAPI MessageBoxExW(HWND,LPCWSTR,LPCWSTR,UINT,WORD);\n"]], ["MessageBoxIndirectA", [nil, "user32", "P", "I", "WINUSERAPI int WINAPI MessageBoxIndirectA(CONST MSGBOXPARAMSA*);\n"]], ["MessageBoxIndirectW", [nil, "user32", "P", "I", "WINUSERAPI int WINAPI MessageBoxIndirectW(CONST MSGBOXPARAMSW*);\n"]]] irb(z:/ara/):009:0> w.MessageBoxA(0,"Hello","title",0) R:1