「Ruby/FFI/サンプル」の編集履歴(バックアップ)一覧はこちら
「Ruby/FFI/サンプル」(2010/03/18 (木) 17:42:37) の最新版変更点
追加された行は緑色になります。
削除された行は赤色になります。
samples
**構造体
ffi-0.5.1で確認
-簡単な例
class XYZ < FFI::Struct
layout :x, :int,
:y, :int,
:z, :int
end
a = XYZ.new
p a[:x]
a[:x] = 3
p a[:x]
-配列メンバ
class TestA < FFI::Struct
layout :a, :int,
:b, [:int, 3],
:c, :int
end
s = TestA.new
p s[:b][2]
s[:b][2] = 100
p s[:b][2]
s[:c] = 5
p s[:b][3]
-共用体
class TestUnion < FFI::Union
layout :a, :int,
:b, :char
end
n = TestUnion.new
p n[:b]
n[:a] = 0xff07
p n[:a]
p n[:b]
-アラインメント
class TestB < FFI::Struct
layout :a, :long_long,
:b, :char
end
p TestB.size
p TestB.align
-文字列
class TestC < FFI::Struct
layout :chars, [:char, 16]
end
tc = TestC.new
p tc[:chars].to_ptr.put_string(0, "0123456789")
p tc[:chars].to_str
p tc[:chars].to_ptr.put_string(0, "ZZZZZ")
p tc[:chars].to_str
p tc[:chars].to_ptr.put_bytes(0, "1234567890123456")
p tc[:chars].to_str
**関数
-Win32 APIの例
module WinUser
extend FFI::Library
ffi_lib 'user32'
ffi_convention(:stdcall)
MB_OK = 1
attach_function(:message_box, :MessageBoxA, [:long, :string, :string, :int], :int)
end
p WinUser.message_box(0, "message", "window caption", WinUser::MB_OK)
-だいたいの流れ
p lib = FFI::DynamicLibrary.open("user32",
FFI::DynamicLibrary::RTLD_LAZY | FFI::DynamicLibrary::RTLD_GLOBAL)
p function = lib.find_function("MessageBoxA") # FFI::Library::Symbol
raise FFI::NotFoundError.new(name, lib.name) unless function
args = [:long, :string, :string, :int].map {|a| FFI.find_type(a) }
ret_type = FFI.find_type(:int)
p invoker = FFI::Function.new(ret_type, args, function, {:convention => :stdcall})
raise FFI::NotFoundError.new(name, lib.name) unless invoker
p r = invoker.call(0, "message", "window caption", 0)
-コールバック (ffi-0.6.3で動作確認。古いバージョンだとダメ)
require 'ffi'
class Window
extend FFI::Library
ffi_lib('user32')
ffi_convention(:stdcall)
[
[:ulong, :uintptr_t],
[:long, :intptr_t],
[:uintptr_t, :HWND],
[:ulong, :DWORD],
[:int, :BOOL],
[:intptr_t, :LPARAM],
[:pointer, :LPTSTR],
].each {|t| typedef(*t) }
callback(:EnumWindowsProc, [:HWND, :LPARAM], :BOOL)
attach_function(:EnumWindows, [:EnumWindowsProc, :LPARAM], :BOOL)
attach_function(:GetWindowTextA, [:HWND, :LPTSTR, :int], :int)
attach_function(:GetClassNameA, [:HWND, :LPTSTR, :int], :int)
attach_function(:IsWindowVisible, [:HWND], :BOOL)
class << self
alias :GetWindowText :GetWindowTextA
alias :GetClassName :GetClassNameA
end
def self.each(lparam=0, &block)
EnumWindows(lparam) {|hwnd, lparam|
block.call(self.new(hwnd), lparam)
}
end
attr_reader :hwnd
def initialize(hwnd)
@hwnd = hwnd
end
def title
pstr = FFI::MemoryPointer.new(1,256)
self.class.GetWindowText(@hwnd, pstr, pstr.size)
pstr.read_string
end
def class_name
pstr = FFI::MemoryPointer.new(1,256)
self.class.GetClassName(@hwnd, pstr, pstr.size)
pstr.read_string
end
def visible?
self.class.IsWindowVisible(@hwnd).nonzero?
end
end
Window.each {|win, lparam|
puts "#{win.title} [#{win.class_name}]" if win.visible?
1
}
samples
**構造体
ffi-0.5.1で確認
-簡単な例
class XYZ < FFI::Struct
layout :x, :int,
:y, :int,
:z, :int
end
a = XYZ.new
p a[:x]
a[:x] = 3
p a[:x]
-配列メンバ
class TestA < FFI::Struct
layout :a, :int,
:b, [:int, 3],
:c, :int
end
s = TestA.new
p s[:b][2]
s[:b][2] = 100
p s[:b][2]
s[:c] = 5
p s[:b][3]
-共用体
class TestUnion < FFI::Union
layout :a, :int,
:b, :char
end
n = TestUnion.new
p n[:b]
n[:a] = 0xff07
p n[:a]
p n[:b]
-アラインメント
class TestB < FFI::Struct
layout :a, :long_long,
:b, :char
end
p TestB.size
p TestB.align
-文字列
class TestC < FFI::Struct
layout :chars, [:char, 16]
end
tc = TestC.new
p tc[:chars].to_ptr.put_string(0, "0123456789")
p tc[:chars].to_str
p tc[:chars].to_ptr.put_string(0, "ZZZZZ")
p tc[:chars].to_str
p tc[:chars].to_ptr.put_bytes(0, "1234567890123456")
p tc[:chars].to_str
**関数
-Win32 APIの例
module WinUser
extend FFI::Library
ffi_lib 'user32'
ffi_convention(:stdcall)
MB_OK = 1
attach_function(:message_box, :MessageBoxA, [:long, :string, :string, :int], :int)
end
p WinUser.message_box(0, "message", "window caption", WinUser::MB_OK)
-だいたいの流れ
p lib = FFI::DynamicLibrary.open("user32",
FFI::DynamicLibrary::RTLD_LAZY | FFI::DynamicLibrary::RTLD_GLOBAL)
p function = lib.find_function("MessageBoxA") # FFI::Library::Symbol
raise FFI::NotFoundError.new(name, lib.name) unless function
args = [:long, :string, :string, :int].map {|a| FFI.find_type(a) }
ret_type = FFI.find_type(:int)
p invoker = FFI::Function.new(ret_type, args, function, {:convention => :stdcall})
raise FFI::NotFoundError.new(name, lib.name) unless invoker
p r = invoker.call(0, "message", "window caption", 0)
-コールバックの例。ウィンドウの列挙 (ffi-0.6.3で動作確認。古いバージョンだとダメ)
require 'ffi'
class Window
extend FFI::Library
ffi_lib('user32')
ffi_convention(:stdcall)
[
[:ulong, :uintptr_t],
[:long, :intptr_t],
[:uintptr_t, :HWND],
[:ulong, :DWORD],
[:int, :BOOL],
[:intptr_t, :LPARAM],
[:pointer, :LPTSTR],
].each {|t| typedef(*t) }
callback(:EnumWindowsProc, [:HWND, :LPARAM], :BOOL)
attach_function(:EnumWindows, [:EnumWindowsProc, :LPARAM], :BOOL)
attach_function(:GetWindowTextA, [:HWND, :LPTSTR, :int], :int)
attach_function(:GetClassNameA, [:HWND, :LPTSTR, :int], :int)
attach_function(:IsWindowVisible, [:HWND], :BOOL)
class << self
alias :GetWindowText :GetWindowTextA
alias :GetClassName :GetClassNameA
end
def self.each(lparam=0, &block)
EnumWindows(lparam) {|hwnd, lparam|
block.call(self.new(hwnd), lparam)
}
end
attr_reader :hwnd
def initialize(hwnd)
@hwnd = hwnd
end
def title
pstr = FFI::MemoryPointer.new(1,256)
self.class.GetWindowText(@hwnd, pstr, pstr.size)
pstr.read_string
end
def class_name
pstr = FFI::MemoryPointer.new(1,256)
self.class.GetClassName(@hwnd, pstr, pstr.size)
pstr.read_string
end
def visible?
self.class.IsWindowVisible(@hwnd).nonzero?
end
end
Window.each {|win, lparam|
puts "#{win.title} [#{win.class_name}]" if win.visible?
1
}
表示オプション
横に並べて表示:
変化行の前後のみ表示: