Project

General

Profile

Bug #11214

Cannot Get Correct Binding from inside of C Method

Added by schneems (Richard Schneeman) about 4 years ago. Updated 7 days ago.

Status:
Closed
Priority:
Normal
Assignee:
-
Target version:
-
[ruby-core:69453]

Description

I am trying to get the arguments passed into a method using the binding. This is possible using pure Ruby:

class RubyBindingClass
  def foo(arg = nil)
    return binding
  end
end

binding = RubyBindingClass.new.foo
puts binding.eval("self")
# => #<RubyBindingClass:0x007fdc5224f7f8>

puts binding.local_variables.inspect
# => [arg]

You can see that the #<RubyBindingClass:0x007fdc5224f7f8> is returned as self and the local_variables correctly reports that arg is in scope. When we access the binding from a C method, we do not get the same information

# Thanks to Frederick Cheung for the code snippet
require 'inline' # $ gem install RubyInline

random_main_variable = 2

class CBindingClass
  inline do |builder|
    builder.include "<time.h>"
    builder.c_raw <<-SRC, :arity => 1
      VALUE foo(VALUE self, VALUE arg){
        VALUE ret = rb_funcall(self, rb_intern("binding"), 0);
        return ret;
      }
    SRC
  end
end

binding = CBindingClass.new.foo(10)

puts binding.eval("self")
# => main

puts binding.local_variables.inspect
# => [:binding, :random_main_variable]

Here you can see that self is reported as main and that local_variables is returning variables from the main scope instead of from within the C method.

I originally stumbled upon this while trying to get access to arguments via TracePoint: http://stackoverflow.com/questions/30584454/get-method-arguments-using-rubys-tracepoint. Is this binding behavior intentional? Should it be possible to get programatic access to arguments passed into a C defined method?

History

Updated by jeremyevans0 (Jeremy Evans) about 1 month ago

  • Status changed from Open to Feedback

I'm fairly sure having binding capture arguments passed to C methods is not possible. Ruby doesn't know the C function's parameter names at runtime. Even if that were possible, you wouldn't be able to handle cases where a C function takes a variable number of arguments (VALUE func(int argc, VALUE *argv, VALUE self)). So that's why the binding does not include C-level information. It is similar to not being able to get the parameter names for methods defined in C via Method#parameters.

In terms of why binding returns variables from the surrounding scope if called from C, I'm not sure. I think the only alternative would be raising an exception. I'm guessing we don't want to change the behavior, as there are libraries that appear to be relying on it:

Do you still consider this a bug?

Updated by chrisseaton (Chris Seaton) about 1 month ago

I'm fairly sure having binding capture arguments passed to C methods is not possible.

TruffleRuby could do that! Sorry I know it's boasting and not relevant to MRI :)

#3

Updated by jeremyevans0 (Jeremy Evans) 7 days ago

  • Status changed from Feedback to Closed

Also available in: Atom PDF