「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 }

表示オプション

横に並べて表示:
変化行の前後のみ表示:
記事メニュー
目安箱バナー