Skip to content
This repository has been archived by the owner on Jul 22, 2024. It is now read-only.

Commit

Permalink
Merge pull request #69 from fabian-f/Instance&GlobalVariables
Browse files Browse the repository at this point in the history
Expose mrb_iv_get/set, mrb_gv_get/set to Go in a consistent fashion.
  • Loading branch information
Erik Hollensbe authored Oct 3, 2018
2 parents 431f823 + 473f089 commit cd6a04a
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 0 deletions.
16 changes: 16 additions & 0 deletions gomruby.h
Original file line number Diff line number Diff line change
Expand Up @@ -252,4 +252,20 @@ static inline struct RObject* _go_mrb_getobj(mrb_value v) {
return mrb_obj_ptr(v);
}

static inline void _go_mrb_iv_set(mrb_state *m, mrb_value self, mrb_sym sym, mrb_value v) {
mrb_iv_set(m, self, sym, v);
}

static inline mrb_value _go_mrb_iv_get(mrb_state *m, mrb_value self, mrb_sym sym) {
return mrb_iv_get(m, self, sym);
}

static inline void _go_mrb_gv_set(mrb_state *m, mrb_sym sym, mrb_value v) {
mrb_gv_set(m, sym, v);
}

static inline mrb_value _go_mrb_gv_get(mrb_state *m, mrb_sym sym) {
return mrb_gv_get(m, sym);
}

#endif
16 changes: 16 additions & 0 deletions mruby.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,22 @@ type Mrb struct {
state *C.mrb_state
}

// GetGlobalVariable returns the value of the global variable by the given name.
func (m *Mrb) GetGlobalVariable(name string) *MrbValue {
cs := C.CString(name)
defer C.free(unsafe.Pointer(cs))
return newValue(m.state, C._go_mrb_gv_get(m.state, C.mrb_intern_cstr(m.state, cs)))
}

// SetGlobalVariable sets the value of the global variable by the given name.
func (m *Mrb) SetGlobalVariable(name string, value Value) {
cs := C.CString(name)
defer C.free(unsafe.Pointer(cs))

v := value.MrbValue(m)
C._go_mrb_gv_set(m.state, C.mrb_intern_cstr(m.state, cs), v.value)
}

// ArenaIndex represents the index into the arena portion of the GC.
//
// See ArenaSave for more information.
Expand Down
64 changes: 64 additions & 0 deletions mruby_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,70 @@ func TestMrbGetArgs(t *testing.T) {
}
}

func TestMrbGlobalVariable(t *testing.T) {
const (
TestValue = "HELLO"
)
mrb := NewMrb()
defer mrb.Close()
if _, err := mrb.LoadString(fmt.Sprintf(`$a = "%s"`, TestValue)); err != nil {
t.Fatalf("err: %s", err)
}
value := mrb.GetGlobalVariable("$a")
if value.String() != TestValue {
t.Fatalf("wrong value for $a: expected '%s', found '%s'", TestValue, value.String())
}
mrb.SetGlobalVariable("$b", mrb.StringValue(TestValue))
value, err := mrb.LoadString(`$b`)
if err != nil {
t.Fatalf("err: %s", err)
}
if value.String() != TestValue {
t.Fatalf("wrong value for $b: expected '%s', found '%s'", TestValue, value.String())
}
}

func TestMrbInstanceVariable(t *testing.T) {
const (
GoldenRetriever = "golden retriever"
Husky = "Husky"
)
mrb := NewMrb()
defer mrb.Close()
_, err := mrb.LoadString(`
class Dog
def initialize(breed)
@breed = breed
end
def breed
"cocker spaniel" # this line exists to ensure that it's not invoking the accessor method
end
def real_breed
@breed
end
end
`)
if err != nil {
t.Fatalf("err: %s", err)
}
dogClass := mrb.Class("Dog", nil)
if dogClass == nil {
t.Fatalf("dog class not found")
}
inst, err := dogClass.New(mrb.StringValue(GoldenRetriever))
if err != nil {
t.Fatalf("err: %s", err)
}
value := inst.GetInstanceVariable("@breed")
if value.String() != GoldenRetriever {
t.Fatalf("wrong value for Dog.@breed. expected: '%s', found: '%s'", GoldenRetriever, value.String())
}
inst.SetInstanceVariable("@breed", mrb.StringValue(Husky))
value = inst.GetInstanceVariable("@breed")
if value.String() != Husky {
t.Fatalf("wrong value for Dog.@breed. expected: '%s', found: '%s'", Husky, value.String())
}
}
func TestMrbLoadString(t *testing.T) {
mrb := NewMrb()
defer mrb.Close()
Expand Down
14 changes: 14 additions & 0 deletions value.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,20 @@ func init() {
Nil = [0]byte{}
}

// SetInstanceVariable sets an instance variable on this value.
func (v *MrbValue) SetInstanceVariable(variable string, value *MrbValue) {
cs := C.CString(variable)
defer C.free(unsafe.Pointer(cs))
C._go_mrb_iv_set(v.state, v.value, C.mrb_intern_cstr(v.state, cs), value.value)
}

// GetInstanceVariable gets an instance variable on this value.
func (v *MrbValue) GetInstanceVariable(variable string) *MrbValue {
cs := C.CString(variable)
defer C.free(unsafe.Pointer(cs))
return newValue(v.state, C._go_mrb_iv_get(v.state, v.value, C.mrb_intern_cstr(v.state, cs)))
}

// Call calls a method with the given name and arguments on this
// value.
func (v *MrbValue) Call(method string, args ...Value) (*MrbValue, error) {
Expand Down

0 comments on commit cd6a04a

Please sign in to comment.