[心得] 用 Rust 撰寫 Ruby gem (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
01/06 00:03, 2F
※ 編輯: Neisseria (59.115.69.164), 01/07/2017 09:28:06
Ruby 近期熱門文章
PTT數位生活區 即時熱門文章