请教大家一个关于调用cdll的问题。如下,我封装了一个C++函数,并暴露出C接口,头文件如下:
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
int row;
int col;
double data;
} cdef_matrix;
typedef struct {
int row;
double data;
} cdef_vector;
typedef struct {
int size;
cdef_vector* data;
} cdef_ret_vector;
extern "C" __declspec(dllimport) cdef_ret_vector* spsolver_LU(cdef_matrix* A, int A_size, cdef_vector* B, int B_size, int row, int col);
#ifdef __cplusplus
}
#endif
rust这边这么构造:
use libloading::{Library, Symbol};
use sprs::CsMat;
fn main() {
spsolver();
}
type SPSolverLU = unsafe fn(*mut cdef_matrix, i32, *mut cdef_vector, i32, i32, i32) -> *mut cdef_ret_vector;
#[repr(C)]
pub struct cdef_matrix {
row: i32,
col: i32,
data: f64,
}
#[repr(C)]
#[derive(Debug)]
pub struct cdef_vector {
row: i32,
data: f64,
}
#[repr(C)]
pub struct cdef_ret_vector {
size: i32,
data: *mut cdef_vector,
}
fn spsolver() {
let lib = Library::new("spsolver_for_rust.dll").unwrap();
unsafe {
let mut a00 = cdef_matrix{row: 0, col: 0, data: 1.0};
let mut a01 = cdef_matrix{row: 0, col: 1, data: 2.0};
let mut a10 = cdef_matrix{row: 1, col: 0, data: 3.0};
let mut a11 = cdef_matrix{row: 1, col: 1, data: 4.0};
let mut a = vec![a00, a01, a10, a11];
let mut b0 = cdef_vector{row: 0, data: 17.0};
let mut b1 = cdef_vector{row: 1, data: 39.0};
let mut b = vec![b0, b1];
let func: Symbol<SPSolverLU> = lib.get(b"spsolver_LU").unwrap();
let x = func(a.as_mut_ptr(), 4, b.as_mut_ptr(), 2, 2, 2);
// rebuild results as Vec<cdef_veoctr>
// A: [[1, 2], [3, 4]] B: [17, 39] -> AX = B -> X:[5, 6]
let x_len = (*x).size as usize;
let x_cap = x_len;
let x_ptr = (*x).data;
let rebuilt_x = Vec::from_raw_parts(x_ptr, x_len, x_cap);
println!("{:?}", rebuilt_x);
}
}
如上程序是可以运行出正确结果的,但实际上我只需要返回一个结构体cdef_ret_vector
,而不是一个结构体数组cdef_ret_vector*
。但是假如我修改两边的定义,不返回指针而是直接返回一个结构体cdef_ret_vector
的话。就各种error: .....access violation
。这是什么原因呢?每次都定义一个结构体数组来返回,逼死强迫症。
貌似不calloc而是直接传结构体的指针也会失败?我有个猜想,是不是rust分配给dll的栈在退出后会直接清除?所以导致只有分配到堆上的数据的指针能被传回来正常使用?
1
共 2 条评论, 1 页
评论区
写评论所以遇到传结构体的地方,统统传指针会比较好是么。但是有了指针之后,访问结构体成员倒是很正常,哎,总之有点纳闷。
--
👇
c5soft: 这个问题应该是涉及到Rust变量在内存中占据的空间大小与变量的生命周期的问题,传指针应该是借用关系,并且指针占用空间大小是固定的,处理起来简单,传递结构体的话那就复杂了,双方需要仔细协商。
这个问题应该是涉及到Rust变量在内存中占据的空间大小与变量的生命周期的问题,传指针应该是借用关系,并且指针占用空间大小是固定的,处理起来简单,传递结构体的话那就复杂了,双方需要仔细协商。