如何在Rust和Python之间传递指针?

Rob*_*ung 10 python ctypes rust

我正在尝试在Rust中编写一个可以从Python代码调用的库.我希望能够将一个void指针传递回Python,以便我可以在调用Rust之间保持状态.但是,当我再次尝试访问指针时,我在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
}
Run Code Online (Sandbox Code Playgroud)
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)
Run Code Online (Sandbox Code Playgroud)

输出

0xdc24000
10dc24000
0xdc24000
[1]    64006 segmentation fault  python src/main.py
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?

She*_*ter 9

eryksun钉了它:

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

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

0x103424000
  103424000
0x  3424000
Run Code Online (Sandbox Code Playgroud)

所以Debug指针的格式化程序应该没问题.不确定为什么你的输出不同.

添加后

lib.continue_state.argtypes = (ctypes.c_void_p,)
Run Code Online (Sandbox Code Playgroud)

程序运行得很好.