Skip to content

Commit 84a3605

Browse files
authored
Merge pull request #323 from ruby-go-gem/feature/RB_GC_GUARD
Impl `RB_GC_GUARD`
2 parents e768c15 + db35a8c commit 84a3605

File tree

3 files changed

+57
-0
lines changed

3 files changed

+57
-0
lines changed

ruby/ruby_internal_memory.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package ruby
2+
3+
/*
4+
#include "ruby.h"
5+
6+
// FIXME: static inline volatile functions can't be called from cgo.
7+
static inline volatile VALUE *
8+
__rb_gc_guarded_ptr(volatile VALUE *ptr)
9+
{
10+
return ptr;
11+
}
12+
13+
*/
14+
import "C"
15+
16+
// c.f. https://github.com/ruby/ruby/blob/master/include/ruby/internal/memory.h
17+
18+
// rbGcGuardedPtr is wrapper for `__rb_gc_guarded_ptr`
19+
func rbGcGuardedPtr(v *VALUE) *C.VALUE {
20+
return C.__rb_gc_guarded_ptr((*C.VALUE)(v))
21+
}
22+
23+
// RB_GC_GUARD calls `RB_GC_GUARD` in C
24+
//
25+
// ref.
26+
// - https://docs.ruby-lang.org/capi/en/master/dc/d18/memory_8h.html
27+
// - https://docs.ruby-lang.org/en/master/extension_rdoc.html
28+
func RB_GC_GUARD(v VALUE) *VALUE {
29+
return (*VALUE)(rbGcGuardedPtr(&v))
30+
}

ruby/testdata/example/ext/example/tests.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,13 @@ VALUE rb_example_tests_rb_ary_shift(VALUE self, VALUE ary);
3131
VALUE rb_example_tests_rb_ary_unshift(VALUE self, VALUE ary, VALUE elem);
3232
void rb_example_tests_rb_define_variable(VALUE self, VALUE name, VALUE v);
3333
void rb_example_tests_rb_define_const(VALUE self, VALUE name, VALUE val);
34+
void rb_example_tests_rb_gc_guard(VALUE self);
3435
*/
3536
import "C"
3637

3738
import (
3839
"github.com/ruby-go-gem/go-gem-wrapper/ruby"
40+
"unsafe"
3941
)
4042

4143
//export rb_example_tests_nop_rb_define_method_id
@@ -269,6 +271,26 @@ func rb_example_tests_rb_define_const(self C.VALUE, name C.VALUE, val C.VALUE) {
269271
ruby.RbDefineConst(ruby.VALUE(self), strName, ruby.VALUE(val))
270272
}
271273

274+
//export rb_example_tests_rb_gc_guard
275+
func rb_example_tests_rb_gc_guard(_ C.VALUE) {
276+
// c.f. https://docs.ruby-lang.org/en/master/extension_rdoc.html
277+
s := ruby.RbStrNewCstr("hello world!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
278+
279+
sptr := ruby.RSTRING_PTR(s)
280+
newPtr := unsafe.Add(unsafe.Pointer(sptr), 6)
281+
w := C.rb_str_new_cstr((*C.char)(newPtr))
282+
283+
ruby.RB_GC_GUARD(s)
284+
285+
newStr := ruby.Value2String((ruby.VALUE)(w))
286+
287+
expected := "world!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
288+
289+
if newStr != expected {
290+
ruby.RbRaise(ruby.VALUE(C.rb_eStandardError), "Expected is %s, but actual is %s", expected, newStr)
291+
}
292+
}
293+
272294
// defineMethodsToExampleTests define methods in Example::Tests
273295
func defineMethodsToExampleTests(rb_mExample ruby.VALUE) {
274296
rb_cTests := ruby.RbDefineClassUnder(rb_mExample, "Tests", ruby.VALUE(C.rb_cObject))
@@ -303,4 +325,5 @@ func defineMethodsToExampleTests(rb_mExample ruby.VALUE) {
303325
ruby.RbDefineSingletonMethod(rb_cTests, "rb_ary_unshift", C.rb_example_tests_rb_ary_unshift, 2)
304326
ruby.RbDefineSingletonMethod(rb_cTests, "rb_define_variable", C.rb_example_tests_rb_define_variable, 2)
305327
ruby.RbDefineSingletonMethod(rb_cTests, "rb_define_const", C.rb_example_tests_rb_define_const, 2)
328+
ruby.RbDefineSingletonMethod(rb_cTests, "rb_gc_guard", C.rb_example_tests_rb_gc_guard, 0)
306329
}

ruby/testdata/example/test/example/tests_test.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,5 +188,9 @@ class RbAttrTest < Test::Unit::TestCase
188188
remove_const(:RB_DEFINE_CONST) if const_defined?(:RB_DEFINE_CONST, false)
189189
end
190190
end
191+
192+
test ".rb_gc_guard" do
193+
Example::Tests.rb_gc_guard
194+
end
191195
end
192196
end

0 commit comments

Comments
 (0)