Skip to content

Instantly share code, notes, and snippets.

@notozeki
Last active March 22, 2023 16:27
Show Gist options
  • Star 25 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save notozeki/7159a9d9ab9707a22129 to your computer and use it in GitHub Desktop.
Save notozeki/7159a9d9ab9707a22129 to your computer and use it in GitHub Desktop.
An example Ruby extension written in Crystal
lib Ruby
type VALUE = Void*
type METHOD_FUNC = VALUE, VALUE -> VALUE # STUB
$rb_cObject : VALUE
fun rb_str_to_str(value: VALUE) : VALUE
fun rb_string_value_cstr(value_ptr: VALUE*) : UInt8*
fun rb_define_class(name: UInt8*, super: VALUE) : VALUE
fun rb_define_method(klass: VALUE, name: UInt8*, func: METHOD_FUNC, argc: Int32)
end
def salute(self: Ruby::VALUE, name: Ruby::VALUE)
rb_str = Ruby.rb_str_to_str(name)
c_str = Ruby.rb_string_value_cstr(pointerof(rb_str))
cr_str = String.new(c_str)
puts "Hello, #{cr_str}!!!"
name
end
fun init = Init_crystal_example_ext
GC.init
LibCrystalMain.__crystal_main(0, Pointer(Pointer(UInt8)).null)
greeter = Ruby.rb_define_class("Greeter", Ruby.rb_cObject)
Ruby.rb_define_method(greeter, "salute", ->salute, 1)
end
CRYSTAL = crystal
UNAME = "$(shell uname -ms)"
LIBRARY_PATH = $(shell brew --prefix crystal-lang)/embedded/lib
LIBS = -levent -lpcl -lpcre -lgc -lpthread
LDFLAGS = -Wl,-undefined,dynamic_lookup
TARGET = crystal_example_ext.bundle
$(TARGET): crystal_example_ext.o
$(CC) -bundle -L$(LIBRARY_PATH) -o $@ $^ $(LIBS) $(LDFLAGS)
crystal_example_ext.o: crystal_example_ext.cr
$(CRYSTAL) build --cross-compile $(UNAME) $<
.PHONY: clean
clean:
rm -f bc_flags
rm -f crystal_example_ext.o
rm -f $(TARGET)
# First, build the extension by running `make`
require './crystal_example_ext'
g = Greeter.new
g.salute('world')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment