1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
use std::alloc::alloc;
use std::alloc::dealloc;
use std::alloc::Layout;
use std::cmp::max;
use std::isize;
use std::mem::align_of;
use std::mem::size_of;
use std::os::raw::c_void;
use std::ptr::null_mut;
const LAYOUT_ALIGNMENT: usize = align_of::<Layout>();
const LAYOUT_SIZE: usize = size_of::<Layout>();
#[no_mangle]
pub unsafe extern "C" fn rust_cpp_new(
size: usize,
alignment: usize,
) -> *mut c_void {
let offset = max(LAYOUT_ALIGNMENT, LAYOUT_SIZE);
let new_alignment = max(offset, alignment);
let new_size = size + new_alignment;
if new_alignment >= (isize::MAX as usize) {
null_mut()
} else {
match Layout::from_size_align(new_size, new_alignment) {
Ok(layout) => {
let allocation = alloc(layout);
let result_allocation =
allocation.offset(new_alignment as isize);
let hidden_allocation =
result_allocation.offset(-(offset as isize)) as *mut Layout;
hidden_allocation.write(layout);
result_allocation as *mut c_void
}
Err(_) => null_mut(),
}
}
}
#[no_mangle]
pub unsafe extern "C" fn rust_cpp_delete(payload: *const c_void) {
let offset = max(LAYOUT_ALIGNMENT, LAYOUT_SIZE);
if !payload.is_null() {
let result_allocation = payload as *mut u8;
let hidden_allocation =
result_allocation.offset(-(offset as isize)) as *const Layout;
let layout = hidden_allocation.read();
let allocation = result_allocation.offset(-(layout.align() as isize));
dealloc(allocation, layout);
}
}
#[link(name = "cpp_new")]
extern "C" {}
#[cfg(test)]
mod tests {
extern crate cpp_new_simple_cpp_lib;
use self::cpp_new_simple_cpp_lib::*;
#[test]
fn new() {
let foo = safe_create_foo();
assert_eq!(foo.i, 42);
assert_eq!(foo.f, 42.0);
assert_eq!(foo.c, 42);
safe_destroy_foo(foo);
}
#[test]
fn array_new() {
let foos = safe_create_foos(512);
for foo in foos.iter() {
assert_eq!(foo.i, 42);
assert_eq!(foo.f, 42.0);
assert_eq!(foo.c, 42);
}
safe_destroy_foos(foos);
}
}