我正在考虑用Rust编写Ruby gem。让我们假设我想在Rust中创建一些结构,这些结构返回到Ruby代码,类似于示例here。在将Point结构添加到我的Ruby代码中时,我想直接调用它的属性。目前我必须做类似的事情:
point.rb:
require "fiddle"
require "fiddle/import"
module RustPoint
extend Fiddle::Importer
dlload "./libmain.dylib"
extern "Point* make_point(int, int)"
extern "double get_distance(Point*, Point*)"
extern "int y(Point*)"
extern "int x(Point*)"
end
main.rs:
use std::num::pow;
pub struct Point { x: int, y: int }
#[no_mangle]
pub extern "C" fn make_point(x: int, y: int) -> Box<Point> {
box Point { x: x, y: y }
}
#[no_mangle]
pub extern "C" fn x(p: &Point) -> int {
p.x
}
#[no_mangle]
pub extern "C" fn y(p: &Point) -> int {
p.y
}
并在Ruby中使用它:
point = RustPoint::make_point(0, 42)
# To get x:
x = RustPoint::x(point)
获取x值。我更喜欢这样的东西:
point = RustPoint::make_point(0, 42)
# To get x:
x = point.x
有没有人知道一个库或一种方法来简化这个实现。我认为如果我从红宝石方面看不出有关点对象的话会更好。我不应该有所作为天气这是一个C扩展,一个Ruby对象或用Rust编写。
编辑:我希望Rust代码的行为类似于原生扩展。因此返回的结构应该可以从Ruby端调用,类似于使用ruby对象作为值的C结构。当然,有一个库可以处理生锈代码中的ruby对象。
答案 0 :(得分:1)
您可以将整个事物包装在自定义委托人中:
class RustDelegator
attr_accessor :__delegate_class__, :__delegate__
def method_missing(method_name, *arguments, &block)
__delegate_class__.public_send(method_name, *__rust_arguments__(arguments), &block)
end
def respond_to_missing(name, include_private = false)
__delegate_class__.respond_to?(name, include_private)
end
private
def __rust_arguments__(arguments)
arguments.unshift(__delegate__)
end
end
class Point < RustDelegator
def initialize(x, y)
self.__delegate_class__ = RustPoint
self.__delegate__ = RustPoint::make_point(0, 42)
end
end
p = Point.new(0, 42)
#=> #<Point:0x007fb4a4b5b9d0 @__delegate__=[0, 42], @__delegate_class__=RustPoint>
p.x
#=> 0
p.y
#=> 42
答案 1 :(得分:0)
Rust也为struct
提供了本机C接口。如果您像这样定义结构:
#[repr(C)]
pub struct Point {
pub x: i32,
pub y: i32
}
它的行为类似于C struct
struct Point
{
int32_t x;
int32_t y;
}
然后,您可以像在任何其他C结构中一样在Ruby中使用它。
我建议使用固定大小的int类型而不是普通的int
,因为你没有真正的担保Rust&#39; int
与C&{39}的int
大小相同}。如果您确实需要使用它,则应该使用libc::c_int
。