[心得] 用 Rust 撰寫 Ruby gem (3)消失
在最後一篇中,我們寫一個 matrix 的例子
我們仍然會使用 struct,但在 struct 中會再包 2D vector
[Update]
加入釋放記憶體相關程式碼,冏rz
想看程式碼的板友,可到以下 repo
https://github.com/cwchentw/libmatrix-rust-demo
首先,用 Rust 撰寫 library 部分程式碼
#[repr(C)]
pub struct Matrix {
m: Vec<Vec<f64>>,
}
#[no_mangle]
pub extern "C" fn matrix_new(nrow: usize, ncol: usize) -> *mut Matrix {
let mut m = Vec::new();
for j in 0..(nrow) {
let mut n = Vec::new();
for i in 0..(ncol) {
n.push(0.0);
}
m.push(n);
}
Box::into_raw(Box::new(Matrix { m: m }))
}
#[no_mangle]
pub extern "C" fn matrix_get_at(matrix: *const Matrix, row: usize, col: usize)
-> f64 {
unsafe { (*matrix).m[row][col] }
}
#[no_mangle]
pub extern "C" fn matrix_set_at(matrix: *mut Matrix, value: f64,
row: usize, col: usize) {
unsafe { (*matrix).m[row][col] = value; }
}
#[no_mangle]
pub extern "C" fn matrix_free(matrix: *mut Matrix) {
if matrix.is_null() {
return
}
unsafe { Box::from_raw(matrix); }
}
雖然,我們沒有真正實作 matrix 的處理,只寫了 getter/setter。
但是,這只是展示使用 2D vector 的程式,就請各位板友包涵
同樣地,加入釋放記憶體相關的程式碼
接著,撰寫相關的 C 程式碼
#include <stdio.h>
void* matrix_new(size_t, size_t);
double matrix_get_at(void*, size_t, size_t);
void matrix_set_at(void*, double, size_t, size_t);
void matrix_free(void*);
int main() {
void* m = matrix_new(3, 3);
printf("(1, 1) = %lf\n", matrix_get_at(m, 1, 1));
matrix_set_at(m, 99, 1, 1);
printf("(1, 1) = %lf\n", matrix_get_at(m, 1, 1));
matrix_free(m);
return 0;
}
同樣地,用 void* 接 Rust 的 struct
接著,撰寫相關的 Ruby 程式碼
require 'ffi'
require 'objspace'
module MyLib
extend FFI::Library
ffi_lib 'c'
ffi_lib 'target/release/libmatrix.so'
attach_function :matrix_new, [:int, :int], :pointer
attach_function :matrix_get_at, [:pointer, :int, :int], :double
attach_function :matrix_set_at, [:pointer, :double, :int, :int], :void
attach_function :matrix_free, [:pointer], :void
class Matrix
def initialize(row, col)
@m = MyLib::matrix_new(row, col)
ObjectSpace.define_finalizer(self, self.class.finalize)
end
def self.finalize
proc { MyLib::matrix_free @m }
end
def get_at(row, col)
MyLib::matrix_get_at(@m, row, col)
end
def set_at(value, row, col)
MyLib::matrix_set_at(@m, value, row, col)
end
end
end
m = MyLib::Matrix.new(3, 3)
puts "(1, 1) = #{m.get_at(1, 1)}"
m.set_at(99, 1, 1)
puts "(1, 1) = #{m.get_at(1, 1)}"
同樣地,稍微包裝函式庫,讓語法更接近 Ruby 的語法
透過以上數個範例,可知 Rust 的確有潛力用在 Rugy gem 的撰寫
不過 Rust 上手難度偏高,板工目前也還在跟 Rust 的編譯器奮戰中 Orz
而且,Rust 的能見度和相關資源仍然較少,也是需要考慮的點
是否要將 Rust 引入自己下一個專案中,就請各位板友自行判斷
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 61.216.1.86
※ 文章網址: https://www.ptt.cc/bbs/Ruby/M.1480582671.A.755.html
推
12/01 20:36, , 1F
12/01 20:36, 1F
推
12/01 22:35, , 2F
12/01 22:35, 2F
※ 編輯: Neisseria (175.182.114.65), 12/04/2016 15:09:51
推
01/18 09:49, , 3F
01/18 09:49, 3F
Crystal 似乎還在 early stage
如果有分享,歡迎貼在版上 XDD
※ 編輯: Neisseria (175.182.119.20), 01/20/2017 09:36:02
推
01/20 14:03, , 4F
01/20 14:03, 4F
Ruby 近期熱門文章
PTT數位生活區 即時熱門文章