Ja, es gibt einen Weg.
Zuerst müssen Sie zugänglich load
Methode von InstructionSequence
machen, die standardmäßig deaktiviert ist:
require 'fiddle'
class RubyVM::InstructionSequence
# Retrieve Ruby Core's C-ext `iseq_load' function address
load_fn_addr = Fiddle::Handle::DEFAULT['rb_iseq_load']
# Retrieve `iseq_load' C function representation
load_fn = Fiddle::Function.new(load_fn_addr,
[Fiddle::TYPE_VOIDP] * 3,
Fiddle::TYPE_VOIDP)
# Make `iseq_load' accessible as `load' class method
define_singleton_method(:load) do |data, parent = nil, opt = nil|
load_fn.call(Fiddle.dlwrap(data), parent, opt).to_value
end
end
Da die RubyVM::InstructionSequence.load
Methode kann als ein Array zusammengestellt VM-Anweisungen laden, können Sie frei diese verwenden für (de) Serialisierung Zwecke:
irb> # compile simple ruby program into its instruction sequence
irb> seq = RubyVM::InstructionSequence.new <<-EOS
irb: p 'Hello, world !'
irb: EOS
=> <RubyVM::InstructionSequence:<compiled>@<compiled>
irb> # serialize sequence as Array instance representation
irb> data = Marshal.dump seq.to_a
=> "\x04\b[\x13\"-YARVInstructionSequence/SimpleDataFormat … ]"
irb> # de-serialize previously serialized sequence
irb> seq_loaded = Marshal.load data
=> ["YARVInstructionSequence/SimpleDataFormat", 2, 2, 1, { … ]
irb> # load deserialized Array back into instruction sequence
irb> new_iseq = RubyVM::InstructionSequence.load seq_loaded
=> <RubyVM::InstructionSequence:<compiled>@<compiled>>
irb> # execute instruction sequence in current context
irb> new_iseq.eval
"Hello, world !"
=> "Hello, world !"
Das ist alles, Leute;)
Das ist sehr nette! Ich mag es, dass alles mit FFI gemacht werden kann. Eine Frage: Diese Technik scheint nur zu funktionieren, wenn der Typ ISEQ_TYPE_TOP ist (also erhält man eine Befehlssequenz über RubyVM :: InstructionSequence.of (method (: foo))) löst eine Exception mit der Nachricht "keine Toplevel InstructionSequence" aus - definierter Weg, um dies zu erreichen, wenn die Befehlssequenz von einem Proc oder einer Methode erhalten wird? Setting Data [9] =: top scheint zu funktionieren, aber ich bin mir nicht sicher, was die Konsequenzen sein könnten. –