Hey,
I'm new at rust but I've been coding for most of my life, I'm trying to write a wrapper against GraphBLAS C lib from SuiteSparse.
I was able to wrap a GrB_Matrix and create it and drop it successfully
However when I try adding a PhantomData to my struct to make it generic I get signal: 11, SIGSEGV: invalid memory reference
This happens when I try to call the C api in Drop
when I do the same but with an actual generic value instead of PhantomData it works.
Example with PhantomData failing
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
use std::mem::{MaybeUninit};
use enum_primitive::*;
use std::marker::PhantomData;
#[macro_use]
extern crate lazy_static;
lazy_static! {
static ref GRB:u32 = unsafe {GrB_init(GrB_Mode_GrB_NONBLOCKING)};
}
enum_from_primitive! {
#[derive(Debug, Copy, Clone, PartialEq)]
#[repr(u32)]
pub enum GrBIndex {
This file has been truncated. show original
I feel the problem is not dropping everything correctly
alice
December 25, 2019, 6:07pm
2
Note that this
#[macro_use]
extern crate lazy_static;
lazy_static! {
static ref TEST: u32 = {
println!("init");
10
};
}
fn main() {
let _ = TEST;
}
does not print anything. If you write let _ = *TEST instead of let _ = TEST, it will print something. This is because lazy_static just creates a new type for each variable with a Deref impl that initializes it an returns a reference to the actual type (in this case u32), but this means you actually have to dereference it to initialize it.
Thanks, that's true, I'll update that, sadly the error is still there.
this one works if I provide a value
pub struct SparseMatrix<T>{
mat: *mut GrB_Matrix,
phantom: T // FIXME: this sould work with a PhantomData but it doesn't
}
alice
December 25, 2019, 7:35pm
4
It's likely to be an issue that happens randomly depending on the mood of the compiler applying optimizations because of something being unsound. I don't think the PhantomData itself is the culprit.
What is the return value of GrB_Matrix_new? It can fail. How do the generated bindings look?
extern "C" {
pub fn GrB_Matrix_new(
A: *mut GrB_Matrix,
type_: GrB_Type,
nrows: GrB_Index,
ncols: GrB_Index,
) -> GrB_Info;
}
pub type GrB_Info = u32;
pub type GrB_Index = u64;
If I remove the GrB_Matrix_free all goes well but I don't get to free the allocated memory managed by GrB_Matrix
This is GrB_Matrix
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct GB_Matrix_opaque {
_unused: [u8; 0],
}
pub type GrB_Matrix = *mut GB_Matrix_opaque;
alice
December 25, 2019, 8:02pm
7
Please surround your code with three backtics
```
// your code goes here
```
1 Like
I tried using null_mut but it failed with GrB_NULL_POINTER
I really think the problem is calling free on something wrong, I added some other calls to get the number of rows for example so the ffi seems to work
impl<'a, T> SparseMatrix<'a, T> {
pub fn new(size: (u64, u64)) -> SparseMatrix<'a, T>{
let _ = *GRB; // make sure lib is init ?
let mut A = MaybeUninit::<GrB_Matrix>::uninit();
let (rows, cols) = size;
unsafe {
GrB_Matrix_new(A.as_mut_ptr() , GrB_BOOL, rows, cols);
};
let mat = A.as_mut_ptr();
println!("MAT {:p}", mat);
SparseMatrix{ mat: mat, _marker: PhantomData, }
}
pub fn rows(&mut self) -> u64 {
let mut P = MaybeUninit::<u64>::uninit();
unsafe {
GrB_Matrix_nrows(P.as_mut_ptr(), *self.mat);
}
unsafe{P.assume_init()}
}
}
for some reason it now works
let mat = A.as_mut_ptr();
println!("MAT {:p}", mat);
SparseMatrix{ mat: mat, _marker: PhantomData, }
why on earth would printing the pointer make it work
Finally settled for
pub struct SparseMatrix<T>{
mat: *mut GrB_Matrix,
_marker: PhantomData<*const T>
}
and this seems to work, thanks for the help
system
Closed
March 25, 2020, 8:04pm
12
This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.