Skip to content

Commit 570a4b0

Browse files
committed
struct, arr update
struct.size: Returns a non-zero actual size CArr: more impl rewrite use super:: => use crate::
1 parent b7f7802 commit 570a4b0

File tree

7 files changed

+103
-39
lines changed

7 files changed

+103
-39
lines changed

crates/lune-std-ffi/src/carr.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use libffi::middle::Type;
22
use mlua::prelude::*;
33

4+
use crate::ctype::libffi_type_ensured_size;
5+
46
// This is a series of some type.
57
// It provides the final size and the offset of the index,
68
// but does not allow multidimensional arrays because of API complexity.
@@ -16,12 +18,22 @@ struct CArr {
1618
libffi_type: Type,
1719
struct_type: Type,
1820
length: usize,
21+
field_size: usize,
1922
size: usize,
2023
}
2124

2225
impl CArr {
23-
fn new(libffi_type: Type, length: usize) {
24-
Self { libffi_type }
26+
fn new(libffi_type: Type, length: usize) -> LuaResult<Self> {
27+
let struct_type = Type::structure(vec![libffi_type.clone(); length]);
28+
let field_size = libffi_type_ensured_size(libffi_type.as_raw_ptr())?;
29+
30+
Ok(Self {
31+
libffi_type,
32+
struct_type,
33+
length,
34+
field_size,
35+
size: field_size * length,
36+
})
2537
}
2638
}
2739

crates/lune-std-ffi/src/cstruct.rs

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
#![allow(clippy::cargo_common_metadata)]
22

3-
use mlua::prelude::*;
4-
5-
use libffi::low::ffi_abi_FFI_DEFAULT_ABI;
6-
use libffi::middle::{Cif, Type};
7-
use libffi::raw::ffi_get_struct_offsets;
83
use std::vec::Vec;
94

10-
use crate::association::{get_association, set_association};
11-
use crate::ctype::{libffi_types_from_table, type_name_from_userdata};
5+
use libffi::{
6+
low,
7+
middle::{Cif, Type},
8+
raw,
9+
};
10+
use mlua::prelude::*;
1211

13-
use super::ctype::CType;
12+
use crate::association::{get_association, set_association};
13+
use crate::ctype::{libffi_types_from_table, type_name_from_userdata, CType};
14+
use crate::FFI_STATUS_NAMES;
1415

1516
pub struct CStruct {
1617
libffi_cif: Cif,
@@ -23,35 +24,48 @@ pub struct CStruct {
2324
const CSTRUCT_INNER: &str = "__cstruct_inner";
2425

2526
impl CStruct {
26-
pub fn new(fields: Vec<Type>) -> Self {
27+
pub fn new(fields: Vec<Type>) -> LuaResult<Self> {
2728
let libffi_type = Type::structure(fields.clone());
2829
let libffi_cfi = Cif::new(vec![libffi_type.clone()], Type::void());
29-
let size = unsafe { (*libffi_type.as_raw_ptr()).size };
30+
31+
// Get field offsets with ffi_get_struct_offsets
3032
let mut offsets = Vec::<usize>::with_capacity(fields.len());
3133
unsafe {
32-
ffi_get_struct_offsets(
33-
ffi_abi_FFI_DEFAULT_ABI,
34+
let offset_result: raw::ffi_status = raw::ffi_get_struct_offsets(
35+
low::ffi_abi_FFI_DEFAULT_ABI,
3436
libffi_type.as_raw_ptr(),
3537
offsets.as_mut_ptr(),
3638
);
39+
if offset_result != raw::ffi_status_FFI_OK {
40+
return Err(LuaError::external(format!(
41+
"ffi_get_struct_offsets failed. expected result {}, got {}",
42+
FFI_STATUS_NAMES[0], FFI_STATUS_NAMES[offset_result as usize]
43+
)));
44+
}
3745
offsets.set_len(offsets.capacity());
3846
}
3947

40-
Self {
48+
// Get tailing padded size of struct
49+
// See http://www.chiark.greenend.org.uk/doc/libffi-dev/html/Size-and-Alignment.html
50+
let size = unsafe { (*libffi_type.as_raw_ptr()).size };
51+
52+
Ok(Self {
4153
libffi_cif: libffi_cfi,
4254
libffi_type,
4355
fields,
4456
offsets,
4557
size,
46-
}
58+
})
4759
}
4860

61+
// Create new CStruct UserData with LuaTable.
62+
// Lock and hold table for .inner ref
4963
pub fn from_lua_table<'lua>(
5064
lua: &'lua Lua,
5165
table: LuaTable<'lua>,
5266
) -> LuaResult<LuaAnyUserData<'lua>> {
5367
let fields = libffi_types_from_table(&table)?;
54-
let cstruct = lua.create_userdata(Self::new(fields))?;
68+
let cstruct = lua.create_userdata(Self::new(fields)?)?;
5569
table.set_readonly(true);
5670
set_association(lua, CSTRUCT_INNER, cstruct.clone(), table)?;
5771
Ok(cstruct)
@@ -81,10 +95,6 @@ impl CStruct {
8195
}
8296
}
8397

84-
pub fn get_type(&self) -> Type {
85-
self.libffi_type.clone()
86-
}
87-
8898
// Get byte offset of nth field
8999
pub fn offset(&self, index: usize) -> LuaResult<usize> {
90100
let offset = self
@@ -94,6 +104,10 @@ impl CStruct {
94104
.to_owned();
95105
Ok(offset)
96106
}
107+
108+
pub fn get_type(&self) -> Type {
109+
self.libffi_type.clone()
110+
}
97111
}
98112

99113
impl LuaUserData for CStruct {

crates/lune-std-ffi/src/ctype.rs

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
11
#![allow(clippy::cargo_common_metadata)]
22

33
use std::borrow::Borrow;
4+
use std::ptr::{self, null_mut};
45

5-
use super::association::{get_association, set_association};
6-
use super::cstruct::CStruct;
7-
use libffi::middle::{Cif, Type};
6+
use libffi::{
7+
low,
8+
middle::{Cif, Type},
9+
raw,
10+
};
811
use lune_utils::fmt::{pretty_format_value, ValueFormatConfig};
912
use mlua::prelude::*;
13+
14+
use crate::association::{get_association, set_association};
15+
use crate::cstruct::CStruct;
16+
use crate::FFI_STATUS_NAMES;
1017
// use libffi::raw::{ffi_cif, ffi_ptrarray_to_raw};
1118

1219
const POINTER_INNER: &str = "__pointer_inner";
@@ -18,9 +25,6 @@ pub struct CType {
1825
name: Option<String>,
1926
}
2027

21-
// TODO: ARR
22-
// TODO: convert
23-
2428
impl CType {
2529
pub fn new(libffi_type: Type, name: Option<String>) -> Self {
2630
let libffi_cfi = Cif::new(vec![libffi_type.clone()], Type::void());
@@ -201,3 +205,26 @@ pub fn type_name_from_userdata(userdata: &LuaAnyUserData) -> LuaResult<String> {
201205
Ok(String::from("unnamed"))
202206
}
203207
}
208+
209+
// Ensure sizeof c-type (raw::libffi_type)
210+
// See: http://www.chiark.greenend.org.uk/doc/libffi-dev/html/Size-and-Alignment.html
211+
pub fn libffi_type_ensured_size(ffi_type: *mut raw::ffi_type) -> LuaResult<usize> {
212+
let mut cif: low::ffi_cif = Default::default();
213+
let result = unsafe {
214+
raw::ffi_prep_cif(
215+
ptr::from_mut(&mut cif),
216+
raw::ffi_abi_FFI_DEFAULT_ABI,
217+
0,
218+
ffi_type,
219+
null_mut(),
220+
)
221+
};
222+
223+
if result != raw::ffi_status_FFI_OK {
224+
return Err(LuaError::external(format!(
225+
"ffi_get_struct_offsets failed. expected result {}, got {}",
226+
FFI_STATUS_NAMES[0], FFI_STATUS_NAMES[result as usize]
227+
)));
228+
}
229+
unsafe { Ok((*ffi_type).size) }
230+
}

crates/lune-std-ffi/src/ffibox.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,13 @@
99
// rather, it creates more heap space, so it should be used appropriately
1010
// where necessary.
1111

12-
use super::association::set_association;
13-
use super::ffiref::FfiRef;
12+
use std::boxed::Box;
13+
1414
use core::ffi::c_void;
1515
use mlua::prelude::*;
16-
use std::boxed::Box;
16+
17+
use crate::association::set_association;
18+
use crate::ffiref::FfiRef;
1719

1820
const BOX_REF_INNER: &str = "__box_ref";
1921

crates/lune-std-ffi/src/ffilib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
use std::ffi::c_void;
22

3-
use super::association::set_association;
43
use dlopen2::symbor::Library;
54
use mlua::prelude::*;
65

6+
use crate::association::set_association;
77
use crate::ffiref::FfiRef;
88

99
pub struct FfiLib(Library);

crates/lune-std-ffi/src/ffiref.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
use super::association::set_association;
21
use core::ffi::c_void;
3-
use mlua::prelude::*;
42
use std::ptr;
53

4+
use mlua::prelude::*;
5+
6+
use crate::association::set_association;
7+
68
// A referenced space. It is possible to read and write through types.
79
// This operation is not safe. This may cause a memory error in Lua
810
// if use it incorrectly.

crates/lune-std-ffi/src/lib.rs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,19 @@ mod ffilib;
1414
mod ffiraw;
1515
mod ffiref;
1616

17-
use self::association::get_table;
18-
use self::cfn::CFn;
19-
use self::cstruct::CStruct;
20-
use self::ctype::create_all_types;
21-
use self::ffibox::FfiBox;
22-
use self::ffilib::FfiLib;
17+
use crate::association::get_table;
18+
use crate::cfn::CFn;
19+
use crate::cstruct::CStruct;
20+
use crate::ctype::create_all_types;
21+
use crate::ffibox::FfiBox;
22+
use crate::ffilib::FfiLib;
23+
24+
pub const FFI_STATUS_NAMES: [&str; 4] = [
25+
"ffi_status_FFI_OK",
26+
"ffi_status_FFI_BAD_TYPEDEF",
27+
"ffi_status_FFI_BAD_ABI",
28+
"ffi_status_FFI_BAD_ARGTYPE",
29+
];
2330

2431
/**
2532
Creates the `ffi` standard library module.

0 commit comments

Comments
 (0)