2

In a Ruby C extension, I would like to call function "rb_eval_string". If Ruby "eval" is monkey patched, is the C function call the monkey patched version, or the original kernel version?

Edit: Monkey patching is meta programming, in this case in the Ruby environment, and would override the Kernel::eval module method. An example would be:

module Kernel
  def self.eval( eval_string, *extra )
    puts eval_string
  end
end

Link: What does 'Monkey Patching' exactly Mean in Ruby?

B. Young
  • 191
  • 1
  • 1
  • 6

2 Answers2

2

I use the Ruby docs source view to test these things out.

For example, the Kernel#eval method doesn't map to rb_eval_string...

...which is a strong hint that rb_eval_string doesn't map to the monkey patched version.

If you dig deeper into the source code you will notice that both the Kernel function and the global function map to the same C function later down the chain, but rb_eval_string is actually closer to the metal and skips some tests and adjustments.

In other words, no, rb_eval_string doesn't map op the Kernel object's virtual map functions (which is what get's updated during monkey patching).

To call the monkey patched version, you will need to invoke rb_funcall2 with the Kernel object.

Myst
  • 18,516
  • 2
  • 45
  • 67
  • 1
    Thanks for not only answering the question, but telling me how to answer the question from the links to the source code. – B. Young Jul 25 '17 at 20:19
  • @B.Young , I'm happy to help I authored the iodine gem, so I know it's hard to get information about authoring C extensions. Please feel free to accept and up vote any answers that help you. You should always be able to do so on your own questions (though it might take reputation before you can do so with other people's Q&As). We normally use up votes instead of thank you comments, to keep comments informational. ☺️ – Myst Jul 25 '17 at 22:31
0

In a Ruby C extension, I would like to call function "rb_eval_string". If Ruby "eval" is monkey patched, is the C function call the monkey patched version, or the original kernel version?

Neither. It calls the C function. It doesn't call either of the Ruby methods, because C doesn't know about Ruby methods.

C doesn't know about monkey patching. There is no such thing as "monkey patching" in C. If you call a C function, you call a C function, not a completely different C function.

If you want to perform a Ruby message send, using Ruby message dispatch rules, you cannot call a C function, or more precisely, you need to call a C function that performs a Ruby message send and does the lookup and so on, which (confusingly) isn't called send in YARV but rather funcall. There are a number of variations of them, all called some variation of rb_funcall.

Jörg W Mittag
  • 363,080
  • 75
  • 446
  • 653