Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何存储和读取RubyVM::指令序列?_Ruby_Yarv - Fatal编程技术网

如何存储和读取RubyVM::指令序列?

如何存储和读取RubyVM::指令序列?,ruby,yarv,Ruby,Yarv,有没有办法将RubyVM::InstructionSequence存储到文件中,并在以后读取 我尝试了Marshal.dump,但没有成功。我收到以下错误: `dump': no _dump_data is defined for class RubyVM::InstructionSequence (TypeError) 鉴于类的方法有限,您可以尝试的事情也有限。您可能只能将其实例保存为字符串: puts RubyVM::InstructionSequence.disasm(proc{puts

有没有办法将RubyVM::InstructionSequence存储到文件中,并在以后读取

我尝试了
Marshal.dump
,但没有成功。我收到以下错误:

`dump': no _dump_data is defined for class RubyVM::InstructionSequence (TypeError)

鉴于类的方法有限,您可以尝试的事情也有限。您可能只能将其实例保存为字符串:

puts RubyVM::InstructionSequence.disasm(proc{puts "foo"})
结果:

== disasm: <RubyVM::InstructionSequence:block in irb_binding@(irb)>=====
== catch table
| catch type: redo   st: 0002 ed: 0009 sp: 0000 cont: 0002
| catch type: next   st: 0002 ed: 0009 sp: 0000 cont: 0009
|------------------------------------------------------------------------
0000 trace            256                                             (   1)
0002 trace            1
0004 putself          
0005 putstring        \"foo\"
0007 opt_send_without_block <callinfo!mid:puts, argc:1, FCALL|ARGS_SIMPLE>
0009 trace            512
0011 leave            
==disasm:=====
==捕获表
|捕捉类型:重做st:0002 ed:0009 sp:0000 cont:0002
|捕捉类型:下一个st:0002 ed:0009 sp:0000 cont:0009
|------------------------------------------------------------------------
0000跟踪256(1)
0002跟踪1
0004普赛尔夫
0005 putstring \“foo\”
0007 opt_发送_,不带_块
0009跟踪512
0011请假
当您想要反序列化它时,您需要解析这个字符串。

是的,有一种方法

首先,您需要使
指令序列
加载
方法可访问,默认情况下禁用该方法:

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
由于
RubyVM::InstructionSequence.load
方法可以将编译后的VM指令作为数组加载,因此您可以自由地将其用于(反)序列化目的:

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 !"
irb>#将简单的ruby程序编译成其指令序列
irb>seq=RubyVM::指令sequence.new data=Marshal.dump seq.to_a
=>“\x04\b[\x13\”-YARVInstructionSequence/SimpleDataFormat…”
irb>#反序列化以前序列化的序列
irb>seq_loaded=Marshal.load数据
=>[“YARVInstructionSequence/SimpleDataFormat”,2,2,1,{…]
irb>#将反序列化数组加载回指令序列
irb>new_iseq=RubyVM::指令sequence.load seq_加载
=> 
irb>#在当前上下文中执行指令序列
irb>新的iseq.eval
“你好,世界!”
=>“你好,世界!”
这就是所有人;)

这很简单

iseq=RubyVM::InstructionSequence.compile(“a=1+2”)#只是一个例子 File.open('iseq.bin','wb'){| File | File.write iseq.to_binary} #后来 RubyVM::InstructionSequence.load_from_binary(File.read('iseq.bin'))。eval#返回3
这真是太棒了!我喜欢所有这些都可以用FFI来完成。一个问题:这项技术似乎只有在类型为ISEQ_type_TOP时才有效(因此,通过RubyVM::InstructionSequence.of(method(:foo))获取指令序列会引发异常,并显示消息“not a toplevel InstructionSequence”“。当指令序列是从proc或方法获得时,是否有一种定义明确的方法使其工作?设置数据[9]=:top似乎工作,但我不确定会产生什么后果。