我想在结构a
上调用方法I
。我被告知Rust无法找到方法,但我不确定原因:
error: no method named `a` found for type `*mut I` in the current scope
--> src/lib.rs:7:16
|
7 | unsafe { i.a(5) }
| ^
这是一个可重复性最小的例子:
extern crate libc;
use self::libc::int32_t;
#[no_mangle]
pub extern "C" fn i_a(i: *mut I) -> *mut int32_t {
unsafe { i.a(5) } // error: no method named `a` found for type `*mut I` in the current scope
}
#[derive(Debug, PartialEq)]
pub struct I {
pub values: Vec<i32>,
}
impl I {
pub fn a(&self, n: i32) -> i32 {
return 0;
}
}
我该如何解决这个问题?
答案 0 :(得分:3)
我想在结构
上调用方法a
I
代码不有结构I;它有可变指针到结构I
。
我强烈建议在与他们进行深入合作之前阅读chapter on raw pointers。 Rust是一种很棒的语言,当你使用安全方面时,编译器很难防止搞砸。当你遇到不安全的你需要知道你在做什么,因为你告诉编译器要退后观察。
引用和原始指针之间的一个特定区别是原始指针可能是NULL
。另一方面,引用可能永远不会是NULL
。这就是为什么每次取消引用原始指针时都需要使用unsafe
块的原因之一。
通常,您check for a NULL
pointer然后将其转换为引用,如果它不是NULL
:
let i = &*i; // For `&T`
let i = &mut *i; // For `&mut T`
现在你有了一个参考,你可以调用方法。
还有辅助函数,如as_ref
:
pub extern "C" fn i_a(i: *mut I) -> int32_t {
match unsafe { i.as_ref() } {
Some(i) => i.a(5),
None => 42,
}
}
该代码还有一个巨大的漏洞等待被利用。 i_a
声称将指针返回到整数,但代码直接返回一个整数。这是一个非常糟糕的不匹配
答案 1 :(得分:3)
让我们删除extern C的东西,它在这里没用:
#[derive(Debug, PartialEq)]
pub struct I {
pub values: Vec<i32>,
}
impl I {
pub fn a(&self, n: i32) -> i32 {
return 0;
}
}
pub fn i_a(i: *mut I) -> i32 {
unsafe { i.a(5) }
}
问题是Rust中的指针非常有限:它们只在the primitive pointer type上实现了方法。
基本上,您可以检查指针是否为空,比较它是否相等,执行一些算术并取消引用它。请注意,很少有操作对指针实际上是不安全的(主要是算术和解除引用)。
要实际使用指针,首先需要取消引用指针以从中获取引用;这是不安全的,但使用引用是安全的。
因此,您可以将i_a
重写为:
pub fn i_a(i: *mut I) -> i32 {
unsafe { (*i).a(5) }
}
或:
pub fn i_a(i: *mut I) -> i32 {
unsafe { &*i }.a(5)
}
然后它会起作用。
答案 2 :(得分:2)
方法a
在技术上采用self: &I
参数(但速记&self
更方便)。因此,该方法需要引用I
。变量i
的类型为*mut I
,但预计会&I
。这些类型显然不匹配。但您可以通过取消引用原始指针并立即再次引用它(i
)轻松地将&I
转换为(&*i).a(42)
。或者,您可以实现指针的方法:
trait A {
fn a(self, n: i32) -> i32;
}
impl A for *mut I {
fn a(self, n: i32) -> i32 {
return 0;
}
}