承接上一篇,这次展示传递 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 的例子