首页 > 解决方案 > C 互操作的原始指针

问题描述

要在 Python 中使用一些 Rust 代码,我认为它需要通过 C 接口传递,为我正在使用的接口(CFFI)执行此操作,我相信我需要返回大量原始指针(它注释The ctype is usually some constant string describing the C type. It must be a pointer or array type.)。我对此有困难。

简明扼要地解释起来有点困难,所以提前,这是一个问题的游乐场:https ://play.rust-lang.org/?version=nightly&mode=release&edition=2018&gist=d541592aa6011e5d67c279680f855743

我有一个返回复杂类型的函数:

fn test_function() -> CArray<CArray<SymbolPixels>> {
    // Just some test data
    let temp: Vec<Vec<(Vec<u8>, Bound<usize>)>> = vec![
        vec![(vec![1,2,3,4,5,6,7],Bound::new())],
        vec![(vec![1,2,3,4,5,6,7],Bound::new()),(vec![1,2,3,4,5,6,7],Bound::new()),(vec![1,2,3,4,5,6,7],Bound::new())]
    ];
    CArray::new(temp.into_iter().map(|sl| {
        CArray::new(sl.into_iter().map(|(s, b)| SymbolPixels { 
            pixels: &CArray::new(s), 
            bound: &ReturnBound::new(b)
        }).collect::<Vec<SymbolPixels>>())
    }).collect::<Vec<CArray<SymbolPixels>>>())
}


#[derive(Clone, Debug)]
pub struct Bound<T: Ord + Copy> {
    pub min: Point<T>,
    pub max: Point<T>,
}
// This impl is just for easy testing here
impl Bound<usize> {
    fn new() -> Bound<usize> {
        Bound { min: Point { x:1, y:2 }, max: Point { x:5, y:9 } }
    }
}

#[repr(C)]
#[derive(Debug)]
pub struct CArray<T> {
    pub ptr: *const T,
    pub size: usize,
}
impl<T> CArray<T> {
    pub fn new(v: Vec<T>) -> Self {
        let (ptr,size,_) = v.into_raw_parts();
        CArray {
            ptr: ptr,
            size: size,
        }
    }
}

#[repr(C)]
#[derive(Debug)]
pub struct SymbolPixels {
    pub pixels: *const CArray<u8>,
    pub bound: *const ReturnBound
}

#[repr(C)]
#[derive(Debug)]
pub struct ReturnBound {
    pub min: *const Point<u32>,
    pub max: *const Point<u32>,
}
impl ReturnBound {
    pub fn new(b: Bound<usize>) -> Self {
        ReturnBound { 
            min: &Point { x: b.min.x as u32, y: b.min.y as u32 },
            max: &Point { x: b.max.x as u32, y: b.max.y as u32 }
        }
    }
}

#[repr(C)]
#[derive(Copy, Clone, Debug)]
pub struct Point<T: Ord> {
    pub x: T,
    pub y: T,
}

目前正在尝试读取返回结果:

fn main() {
    let segment = test_function();
    unsafe {
        println!("segment: {:.?}",segment);
        let lines = std::slice::from_raw_parts(segment.ptr, segment.size);
        println!("lines: {:.?}",lines);
        for line in lines.iter() {
            let symbols = std::slice::from_raw_parts(line.ptr, line.size);
            for s in symbols.iter() {
                println!("{:.?}",*s.bound);
                // THE PROBLEM:
                // The below line doesn't work
                println!("{:.?}",*(s.bound).min);
                // (Rust throws an error and it simply crashes the Python program when access is attempted)
            }
        }
    }
}

我收到错误消息(有时操场会崩溃):

   Compiling playground v0.0.1 (/playground)
error[E0615]: attempted to take value of method `min` on type `*const ReturnBound`
  --> src/main.rs:16:45
   |
16 |                 println!("{:.?}",*(s.bound).min);
   |                                             ^^^ method, not a field
   |
help: use parentheses to call the method
   |
16 |                 println!("{:.?}",*(s.bound).min(_));
   |                                                ^^^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0615`.
error: could not compile `playground`

To learn more, run the command again with --verbose.

我相当确定这是我在这里滥用指针的结果,我非常感谢任何帮助。

标签: cpointersrust

解决方案


编译器错误消息具有误导性。试试println!("{:.?}",(*s.bound).min);吧。


推荐阅读