[心得] 用 Rust 撰寫 Ruby gem (1)消失

看板Ruby作者時間7年前 (2016/12/01 16:21), 7年前編輯推噓2(200)
留言2則, 2人參與, 最新討論串1/1
雖然 Ruby 語法優美又很好用 有時候,我們需要程式的執行效率時,Ruby 可能就不夠用了 傳統上,可用 C/C++ 或是 Java 實作需要效能的區塊 上次板工介紹 golang,也可參考 (實用度尚待考驗) 這次板工會使用 Rust 撰寫給 Ruby 使用的 shared library 想法如下: Ruby --> Ruby FFI --> Rust (as C Library) 這次沒有寫成 gem,有點標題騙人 (遮臉) 主要是展示如何結合 Ruby 和 Rust 有興趣的板友可繼續深入,嘗試撰寫 gem 預計寫三篇,本篇是第一篇 [Update] 板工最近在 The Rust FFI Omnibus 爬文 才發現自己的程式碼會造成 memory leak (遮臉) 重點在於要在 Rust 層面釋放記憶體 經板工修改及檢查,目前程式碼沒有 memory leak 如果想直接觀看程式碼,可到以下 repo https://github.com/cwchentw/libdoubler-rust-demo 首先,以 Rust 實作 library 部分的 code extern crate libc; use std::ffi::{CStr, CString}; use libc::c_char; #[no_mangle] pub extern "C" fn double_int(x: i32) -> i32 { x * 2 } #[no_mangle] pub extern "C" fn double_float(x: f64) -> f64 { x * 2.0 } #[no_mangle] pub extern "C" fn double_str(x: *const c_char) -> *const c_char { let string = unsafe { CStr::from_ptr(x).to_str().unwrap() }; let output = format!("{}{}", string, string); CString::new(output).unwrap().into_raw() } #[no_mangle] pub extern "C" fn str_free(x: *mut c_char) { if x.is_null() { return } unsafe { Box::from_raw(x); } } 其中,整數和浮點數的部分可直接傳遞,而 C-style char* string 和 Rust string 則需要做一些轉換。加入釋放記憶體的相關程式碼。 用 Cargo 編譯專案 $ cargo build --release 之後會得到 target/release/libdoubler.so (依平台有所不同) 但是不會自動生成 header file,要自己手動撰寫 這裡我們沒有另外撰寫 header file,而是直接在 C 主程式中呼叫 #include <stdio.h> int double_int(int); double double_float(double); char* double_str(char*); void str_free(char*); int main() { printf("%d\n", double_int(2)); printf("%lf\n", double_float(1.3)); char* str = double_str("Hi"); printf("%s\n", str); str_free(str); return 0; } 接著,撰寫相關 Ruby 程式碼,透過 FFI 模組來橋接 library require 'ffi' module MyLib extend FFI::Library ffi_lib 'c' ffi_lib 'target/release/libdoubler.so' attach_function :double_int, [:int], :int attach_function :double_float, [:double], :double attach_function :double_str, [:string], :string end puts MyLib::double_int(2) puts MyLib::double_float(1.3) puts MyLib::double_str('Hi') 如果在 Ruby 程式碼中額外加入釋放記憶體的部分,反而會引發錯誤 經板工測試,Ruby 似乎會自動釋放 char* string 部分的記憶體 細心的網友會發現,如果只能傳遞整數、浮點數、字串這種基本型別 能夠應用的場合相對受限,而 Rust 可以傳遞 struct 在下一篇中,會展示傳遞 C-style struct -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 61.216.1.86 ※ 文章網址: https://www.ptt.cc/bbs/Ruby/M.1480580491.A.0A8.html

12/01 20:59, , 1F
推推!
12/01 20:59, 1F
※ 編輯: Neisseria (175.182.114.65), 12/04/2016 15:00:23 ※ 編輯: Neisseria (211.72.12.139), 12/05/2016 17:10:12

01/06 00:03, , 2F
不太懂還是推一個XD
01/06 00:03, 2F
※ 編輯: Neisseria (59.115.69.164), 01/07/2017 09:28:06
文章代碼(AID): #1OFzsB2e (Ruby)
文章代碼(AID): #1OFzsB2e (Ruby)