summaryrefslogtreecommitdiff
path: root/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/src/lib.rs')
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/src/lib.rs51
1 files changed, 51 insertions, 0 deletions
diff --git a/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/src/lib.rs b/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/src/lib.rs
new file mode 100644
index 0000000000..0626f04e0f
--- /dev/null
+++ b/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/src/lib.rs
@@ -0,0 +1,51 @@
+extern crate rb_sys;
+
+use rb_sys::{
+ rb_define_module, rb_define_module_function, rb_string_value_cstr, rb_utf8_str_new, VALUE,
+};
+use std::ffi::{CStr, CString};
+use std::os::raw::{c_char, c_long};
+
+#[inline]
+unsafe fn cstr_to_string(str: *const c_char) -> String {
+ CStr::from_ptr(str).to_string_lossy().into_owned()
+}
+
+#[no_mangle]
+unsafe extern "C" fn pub_reverse(_klass: VALUE, mut input: VALUE) -> VALUE {
+ let ruby_string = cstr_to_string(rb_string_value_cstr(&mut input));
+ let reversed = ruby_string.to_string().chars().rev().collect::<String>();
+ let reversed_cstring = CString::new(reversed).unwrap();
+ let size = ruby_string.len() as c_long;
+
+ rb_utf8_str_new(reversed_cstring.as_ptr(), size)
+}
+
+#[cfg(rubygems)]
+#[no_mangle]
+pub extern "C" fn hello_from_rubygems() {}
+
+#[cfg(rubygems_0_0_0)]
+#[no_mangle]
+pub extern "C" fn should_never_exist() {}
+
+#[cfg(rubygems_x_x_x)]
+#[no_mangle]
+pub extern "C" fn hello_from_rubygems_version() {}
+
+#[allow(non_snake_case)]
+#[no_mangle]
+pub extern "C" fn Init_rust_ruby_example() {
+ let name = CString::new("RustRubyExample").unwrap();
+ let function_name = CString::new("reverse").unwrap();
+ // bindgen does not properly detect the arity of the ruby callback function, so we have to transmute
+ let callback = unsafe {
+ std::mem::transmute::<
+ unsafe extern "C" fn(VALUE, VALUE) -> VALUE,
+ unsafe extern "C" fn() -> VALUE,
+ >(pub_reverse)
+ };
+ let klass = unsafe { rb_define_module(name.as_ptr()) };
+
+ unsafe { rb_define_module_function(klass, function_name.as_ptr(), Some(callback), 1) }
+}