模組 Fiddle::CStructBuilder
Fiddle::Importer#struct
和 Fiddle::Importer#union
以易於使用的方式包裝此功能。
公開類別方法
create(klass, types, members) 按一下以切換來源
建構新的類別,給定 C
-
types
(Fiddle::TYPE_INT、Fiddle::TYPE_SIZE_T 等,請參閱 C 類型常數) -
對應的
members
Fiddle::Importer#struct
和 Fiddle::Importer#union
以易於使用的方式包裝此功能。
範例
require 'fiddle/struct' require 'fiddle/cparser' include Fiddle::CParser types, members = parse_struct_signature(['int i','char c']) MyStruct = Fiddle::CStructBuilder.create(Fiddle::CUnion, types, members) MyStruct.malloc(Fiddle::RUBY_FREE) do |obj| ... end obj = MyStruct.malloc(Fiddle::RUBY_FREE) begin ... ensure obj.call_free end obj = MyStruct.malloc begin ... ensure Fiddle.free obj.to_ptr end
# File ext/fiddle/lib/fiddle/struct.rb, line 215 def create(klass, types, members) new_class = Class.new(klass){ define_method(:initialize){|addr, func = nil| if addr.is_a?(self.class.entity_class) @entity = addr else @entity = self.class.entity_class.new(addr, types, func) end @entity.assign_names(members) } define_method(:[]) { |*args| @entity.send(:[], *args) } define_method(:[]=) { |*args| @entity.send(:[]=, *args) } define_method(:to_ptr){ @entity } define_method(:to_i){ @entity.to_i } define_singleton_method(:types) { types } define_singleton_method(:members) { members } # Return the offset of a struct member given its name. # For example: # # MyStruct = struct [ # "int64_t i", # "char c", # ] # # MyStruct.offsetof("i") # => 0 # MyStruct.offsetof("c") # => 8 # define_singleton_method(:offsetof) { |name| klass.offsetof(name, members, types) } members.each{|name| name = name[0] if name.is_a?(Array) # name is a nested struct next if method_defined?(name) define_method(name){ @entity[name] } define_method(name + "="){|val| @entity[name] = val } } entity_class = klass.entity_class alignment = entity_class.alignment(types) size = entity_class.size(types) define_singleton_method(:alignment) { alignment } define_singleton_method(:size) { size } define_singleton_method(:malloc) do |func=nil, &block| if block entity_class.malloc(types, func, size) do |entity| block.call(new(entity)) end else new(entity_class.malloc(types, func, size)) end end } return new_class end
私人實例方法
create(klass, types, members) 按一下以切換來源
建構新的類別,給定 C
-
types
(Fiddle::TYPE_INT、Fiddle::TYPE_SIZE_T 等,請參閱 C 類型常數) -
對應的
members
Fiddle::Importer#struct
和 Fiddle::Importer#union
以易於使用的方式包裝此功能。
範例
require 'fiddle/struct' require 'fiddle/cparser' include Fiddle::CParser types, members = parse_struct_signature(['int i','char c']) MyStruct = Fiddle::CStructBuilder.create(Fiddle::CUnion, types, members) MyStruct.malloc(Fiddle::RUBY_FREE) do |obj| ... end obj = MyStruct.malloc(Fiddle::RUBY_FREE) begin ... ensure obj.call_free end obj = MyStruct.malloc begin ... ensure Fiddle.free obj.to_ptr end
# File ext/fiddle/lib/fiddle/struct.rb, line 215 def create(klass, types, members) new_class = Class.new(klass){ define_method(:initialize){|addr, func = nil| if addr.is_a?(self.class.entity_class) @entity = addr else @entity = self.class.entity_class.new(addr, types, func) end @entity.assign_names(members) } define_method(:[]) { |*args| @entity.send(:[], *args) } define_method(:[]=) { |*args| @entity.send(:[]=, *args) } define_method(:to_ptr){ @entity } define_method(:to_i){ @entity.to_i } define_singleton_method(:types) { types } define_singleton_method(:members) { members } # Return the offset of a struct member given its name. # For example: # # MyStruct = struct [ # "int64_t i", # "char c", # ] # # MyStruct.offsetof("i") # => 0 # MyStruct.offsetof("c") # => 8 # define_singleton_method(:offsetof) { |name| klass.offsetof(name, members, types) } members.each{|name| name = name[0] if name.is_a?(Array) # name is a nested struct next if method_defined?(name) define_method(name){ @entity[name] } define_method(name + "="){|val| @entity[name] = val } } entity_class = klass.entity_class alignment = entity_class.alignment(types) size = entity_class.size(types) define_singleton_method(:alignment) { alignment } define_singleton_method(:size) { size } define_singleton_method(:malloc) do |func=nil, &block| if block entity_class.malloc(types, func, size) do |entity| block.call(new(entity)) end else new(entity_class.malloc(types, func, size)) end end } return new_class end