Numpy数组因ndpointer而生锈,在Windows中失败(在Linux上工作)

Numpy数组因ndpointer而生锈,在Windows中失败(在Linux上工作),numpy,rust,ffi,Numpy,Rust,Ffi,目的:通过ctypes将np.ASCONTIGOUUSARRAY传递给Rust函数。Rust会对阵列进行各种更改。进程在Python中继续。代码在Linux环境中按预期运行(Linux上内置的rust cargo stable,从Manjaro 4.19内核中的Python 3.8调用),但会引发错误:OSError:exception:访问冲突读取0xFFFFFFFFFFFF(有关Windows构建条件,请参阅下文) (简化)代码: 实际生锈功能更复杂。这个小小的剪报足以证明它在Linux中工

目的:通过ctypes将np.ASCONTIGOUUSARRAY传递给Rust函数。Rust会对阵列进行各种更改。进程在Python中继续。代码在Linux环境中按预期运行(Linux上内置的rust cargo stable,从Manjaro 4.19内核中的Python 3.8调用),但会引发错误:OSError:exception:访问冲突读取0xFFFFFFFFFFFF(有关Windows构建条件,请参阅下文)

(简化)代码:

实际生锈功能更复杂。这个小小的剪报足以证明它在Linux中工作,同时在Windows中引发了一个例外

//Rust:
#[no_mangle]
pub extern "C" fn proc_array(data: &mut [f64], count : usize) -> usize {
    println!("In Windows Array Test: received {} items...", count);
    let e = count - 1;
    // Next Line is where the exception is raised:
    println!("Start & End: {:.4}, {:.4}", data[0], data[e]);
    data[0] += 200.0;
    data[e] *= 2.0;
    println!("Start & End: {:.4}, {:.4}", data[0], data[e]);
    let pairs : usize = count / 2;
    pairs
}
我知道异常是在它第一次尝试读取
数据[0]
的行中引发的(我还运行了一些更简短的版本,其中还涉及到例如
let x:f64=data[0]
,以证明引发异常的是对
数据[0]
的第一次读取操作。)

也知道:
windows版本是在windows中的rust cargo下编译的。 如果使用windows gnu或windows msvc工具链编译,则行为相同。 在所有情况下:
print(十六进制(c.uu数组uu接口uu['data']][0])
显示
c数组
的地址,例如
0x225108514c0
,这是预期的,当然不是0xfffffffffff(它指向月球,当然在我的32GB内存中没有任何地方…)


我的结论是,windows中的Python传递指针的方式与Linux中的不同,在windows下我需要以不同的方式传递指针,但在我的搜索中,我没有发现任何东西能够回答这一点。

遵循Jmb的建议 及

  • ,
  • 来自Rust编译器的“帮助”响应
下面实现了将np.ascontiguousarray传递给Rust的既定目标,这样就可以使用python调用程序可用的更改对其进行变异,同时使用相同的代码服务于windows调用程序和linux调用程序


struct Node {
    x : f64,
    y : f64,
    //  ... (real version has additional fields used elsewhere)
}

#[no_mangle]
pub extern "C" fn array_test(dptr: *mut f64, count : usize) -> usize {
    println!("In Windows Array Test: received {} items...", count);
    let data : &mut[f64] = unsafe {
        assert!(!dptr.is_null());
        std::slice::from_raw_parts_mut(dptr, count)
    };
    let pairs : usize = count / 2;

    // populate the structs
    let mut nodes : Vec<Node> = Vec::with_capacity(pairs); 
    for i in (0..count).filter(|x| (x % 2 == 0)) {
        nodes.push(Node { x: data[i], y : data[i+1] } );
    }
    // actual detail of the changes made to the data 
    // not relevant to this question    
    
    // write x & y's back to the data buffer
    for i in 0..pairs {
        data[i * 2] = nodes[i].x;
        data[(i * 2) + 1] = nodes [i].y;
    }
    //  placeholder return:
    pairs
}

结构节点{
x:f64,
y:f64,
//…(真实版本在其他地方使用了其他字段)
}
#[没有损坏]
发布外部“C”fn数组_测试(dptr:*mut f64,计数:usize)->usize{
println!(“在Windows数组测试中:收到{}项…”,计数);
let数据:&mut[f64]=不安全{
断言!(!dptr.is_null());
标准::切片::来自原始零件(dptr,计数)
};
let pairs:usize=count/2;
//填充结构
让mut节点:Vec=Vec::具有_容量(对);
对于(0..count.filter(|x |(x%2==0))中的i{
push(节点{x:data[i],y:data[i+1]});
}
//对数据所做更改的实际详细信息
//与这个问题无关
//将x&y写回数据缓冲区
对我来说,一对一对{
数据[i*2]=节点[i].x;
数据[(i*2)+1]=节点[i].y;
}
//占位符返回:
对
}

这在两个环境Win 10普通linux中进行了测试(在我使用的系统中…很抱歉,我刚才没有能力在其他配置上测试此方法)

rust函数的
数据
参数应该是指向
f64
的指针,而不是一个片段。请参阅:返回类型之间也存在不匹配。Rust代码返回一个
u32
,但是Python代码声明
process\u array.restype=ctypes.c\u size\u t
。并且直接传递一个numpy数组(假设它是指向c样式数组的指针)似乎也有点过于乐观。也许是个好主意。这些评论都帮了大忙。只要我有足够的分数,我就会回来加选票!

struct Node {
    x : f64,
    y : f64,
    //  ... (real version has additional fields used elsewhere)
}

#[no_mangle]
pub extern "C" fn array_test(dptr: *mut f64, count : usize) -> usize {
    println!("In Windows Array Test: received {} items...", count);
    let data : &mut[f64] = unsafe {
        assert!(!dptr.is_null());
        std::slice::from_raw_parts_mut(dptr, count)
    };
    let pairs : usize = count / 2;

    // populate the structs
    let mut nodes : Vec<Node> = Vec::with_capacity(pairs); 
    for i in (0..count).filter(|x| (x % 2 == 0)) {
        nodes.push(Node { x: data[i], y : data[i+1] } );
    }
    // actual detail of the changes made to the data 
    // not relevant to this question    
    
    // write x & y's back to the data buffer
    for i in 0..pairs {
        data[i * 2] = nodes[i].x;
        data[(i * 2) + 1] = nodes [i].y;
    }
    //  placeholder return:
    pairs
}