我正在try 用Rust编写一个库,我可以从Python代码中调用它.我希望能够将一个空指针传递回Python,这样我就可以在调用Rust之间保持状态.然而,当我再次try 访问指针时,却发现 rust 迹斑斑.

完整代码示例和崩溃报告:https://gist.github.com/robyoung/3644f13a05c95cb1b947

密码

#![feature(libc)]
#![feature(alloc)]
extern crate libc;
use std::boxed;

pub struct Point {
    x: i64,
    y: i32,
}

#[no_mangle]
pub extern "C" fn start_state() -> *mut Point {
    let point = Box::new(Point{x: 0, y: 10});
    let raw = unsafe { boxed::into_raw(point) };
    println!("{:?}", raw);
    raw
}

#[no_mangle]
pub extern "C" fn continue_state(point: *mut Point) -> i32 {
    println!("{:?}", point);
    let p = unsafe { Box::from_raw(point) };
    println!("{} {}", p.x, p.y);
    0
}
import ctypes

lib = ctypes.cdll.LoadLibrary('target/libpytesttype.so')
lib.start_state.restype = ctypes.c_void_p

pointer = lib.start_state()
print("{:x}".format(pointer))
lib.continue_state(pointer)

输出

0xdc24000
10dc24000
0xdc24000
[1]    64006 segmentation fault  python src/main.py

我做错了什么?

推荐答案

eryksun nailed it:

在Python方面,您缺少lib.继续你的状态.argtypes=(ctypes.c_void_p,).在不将参数定义为指针的情况下,ctypes使用Python整数的默认转换,该转换将值截断为32位,例如0x0dc24000.如果幸运的话,访问该地址会立即触发segfault.

我的输出(使用我自己的填充)是:

0x103424000
  103424000
0x  3424000

所以指针的Debug格式应该可以.不知道为什么你的输出不同.

加上

lib.continue_state.argtypes = (ctypes.c_void_p,)

程序运行得很好.

Rust相关问答推荐

如何使用Match比较 struct 中的值

将数组转换为HashMap的更简单方法

有没有一种惯用的方法来判断VEC中是否存在变体?

在我的Cargo 中,当我在建筑物中使用时,找不到我可以在产品包中使用的 crate .r我如何解决这个问题?

你能在Rust中弃用一个属性吗?

实现 Deref 的 struct 可以返回对外部数据的引用吗?

RUST 中的读写器锁定模式

使用 pyo3 将 Rust 转换为 Python 自定义类型

如何正确使用git2::Remote::push?

将 &str 或 String 保存在变量中

Sized问题的动态调度迭代器Rust

一旦令牌作为文字使用,声明宏不匹配硬编码值?

如何从 rust 中的同一父目录导入文件

以 `static` 为前缀的闭包是什么意思?我什么时候使用它?

如何将 Rust 中的树状 struct 展平为 Vec<&mut ...>?

Rust - 在线程之间不安全地共享没有互斥量的可变数据

基于名称是否存在的条件编译

在 macro_rules 中转义 $ 美元符号

函数参数的 Rust 功能标志

如果参数为 Send,则返回 Future Send