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

看板Ruby作者時間8年前 (2016/12/01 16:37), 8年前編輯推噓0(000)
留言0則, 0人參與, 最新討論串1/1
承接上一篇,這次展示傳遞 struct [Update] 修正 memory leak 相關 bug,歹勢 Orz 想直接看程式碼的話,可到以下 repo https://github.com/cwchentw/libpoint-rust-demo 首先,以 Rust 實作 library 部分程式碼 #[repr(C)] pub struct Point { x: f64, y: f64, } #[no_mangle] pub extern "C" fn point_new(x: f64, y: f64) -> *const Point { Box::into_raw(Box::new(Point { x: x, y: y })) } #[no_mangle] pub extern "C" fn point_get_x(p: *const Point) -> f64 { unsafe { (*p).x } } #[no_mangle] pub extern "C" fn point_get_y(p: *const Point) -> f64 { unsafe { (*p).y } } #[no_mangle] pub extern "C" fn point_free(p: *mut Point) { if p.is_null() { return } unsafe { Box::from_raw(p); } } 仔細觀看程式碼,可以發現充滿 C-style 的物件導向寫法 另外可以注意的點,在於用 Box 包裝 pointer to struct 加入釋放記憶體相關程式碼 接著,撰寫相關的 C 程式碼 #include <stdio.h> void* point_new(double, double); double point_get_x(void*); double point_get_y(void*); void point_free(void*); int main() { void* p = point_new(6, 4); printf("(%lf, %lf)\n", point_get_x(p), point_get_y(p)); point_free(p); return 0; } 由以上程式碼可看出,在 C 的層級,就是用萬用的 void* 去接 Rust 的 struct 已加入釋放記憶體相關程式碼 接著,撰寫相關的 Ruby 程式碼 require 'ffi' require 'objspace' module MyLib extend FFI::Library ffi_lib 'c' ffi_lib 'target/release/libpoint.so' attach_function :point_new, [:double, :double], :pointer attach_function :point_get_x, [:pointer], :double attach_function :point_get_y, [:pointer], :double attach_function :point_free, [:pointer], :void class Point def initialize(x, y) @p = MyLib::point_new x, y ObjectSpace.define_finalizer(self, self.class.finalize) end def self.finalize proc { MyLib::point_free @p } end def x MyLib::point_get_x @p end def y MyLib::point_get_y @p end end end p = MyLib::Point.new(6, 4) puts "(#{p.x}, #{p.y})" 在這裡,我們稍微包裝一下函式庫,使得語法較接近 Ruby 的慣用語法 由以上範例可觀察出,Rust 可傳遞 struct,使得可應用的範圍就廣得多 在下一個範例中,會展示另一個用 struct 的例子 -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 61.216.1.86 ※ 文章網址: https://www.ptt.cc/bbs/Ruby/M.1480581461.A.1D6.html ※ 編輯: Neisseria (175.182.114.65), 12/04/2016 15:05:26
文章代碼(AID): #1OF-5L7M (Ruby)
文章代碼(AID): #1OF-5L7M (Ruby)