Skip to content

Instantly share code, notes, and snippets.

@eregon
Created January 28, 2021 14:15
Show Gist options
  • Save eregon/31259907c132ab61e9f136d684b1fc39 to your computer and use it in GitHub Desktop.
Save eregon/31259907c132ab61e9f136d684b1fc39 to your computer and use it in GitHub Desktop.
Mixing Ruby code and C extension code in a single file
require 'tmpdir'
require 'rbconfig'
def inline_c_extension(c_code)
Dir.mktmpdir('inline_c_extension') do |dir|
File.write("#{dir}/cext.c", c_code)
File.write("#{dir}/extconf.rb", <<~RUBY)
require 'mkmf'
create_makefile('cext')
RUBY
out = IO.popen([RbConfig.ruby, 'extconf.rb'], chdir: dir, &:read)
raise "ruby extconf.rb failed: #{$?.inspect}\n#{out}" unless $?.success?
out = IO.popen(['make'], chdir: dir, &:read)
raise "make failed: #{$?.inspect}\n#{out}" unless $?.success?
require "#{dir}/cext.#{RbConfig::CONFIG['DLEXT']}"
end
end
inline_c_extension <<~C
#include "ruby.h"
static VALUE fibonacci(VALUE self, VALUE n) {
long prev = 0, cur = 1;
for (int i = 0; i < FIX2INT(n); i++) {
long next = prev + cur;
prev = cur;
cur = next;
}
return LONG2FIX(prev);
}
void Init_cext(void) {
VALUE c = rb_define_class("Fib", rb_cObject);
rb_define_singleton_method(c, "fibonacci", fibonacci, 1);
}
C
(0..20).each { |i| p [i, Fib.fibonacci(i)] }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment