Skip to content

Commit 036d3ae

Browse files
authored
Closes #274: Adding FFI functions for bool, float, double, string, vecbytes (#950)
- Add Tests for CAPI Flatbuffers - Separate function for creating Uninitialized Sandbox for C guests - Ignore Test cases for float and double until Github issue #179 is fixed. Signed-off-by: Shailesh Vashishth <[email protected]>
1 parent 99c217c commit 036d3ae

File tree

4 files changed

+221
-3
lines changed

4 files changed

+221
-3
lines changed

src/hyperlight_guest_capi/src/flatbuffer.rs

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ limitations under the License.
1515
*/
1616

1717
use alloc::boxed::Box;
18+
use alloc::ffi::CString;
19+
use alloc::string::String;
20+
use alloc::vec::Vec;
1821
use core::ffi::{CStr, c_char};
1922

2023
use hyperlight_common::flatbuffer_wrappers::util::get_flatbuffer_result;
@@ -92,6 +95,13 @@ pub extern "C" fn hl_flatbuffer_result_from_Bytes(data: *const u8, len: usize) -
9295
Box::new(unsafe { FfiVec::from_vec(vec) })
9396
}
9497

98+
#[unsafe(no_mangle)]
99+
pub extern "C" fn hl_flatbuffer_result_from_Bool(value: bool) -> Box<FfiVec> {
100+
let vec = get_flatbuffer_result(value);
101+
102+
Box::new(unsafe { FfiVec::from_vec(vec) })
103+
}
104+
95105
//--- Functions for getting values returned by host functions calls
96106

97107
#[unsafe(no_mangle)]
@@ -115,4 +125,34 @@ pub extern "C" fn hl_get_host_return_value_as_ULong() -> u64 {
115125
get_host_return_value().expect("Unable to get host return value as ulong")
116126
}
117127

118-
// TODO add bool, float, double, string, vecbytes
128+
#[unsafe(no_mangle)]
129+
pub extern "C" fn hl_get_host_return_value_as_Bool() -> bool {
130+
get_host_return_value().expect("Unable to get host return value as bool")
131+
}
132+
133+
#[unsafe(no_mangle)]
134+
pub extern "C" fn hl_get_host_return_value_as_Float() -> f32 {
135+
get_host_return_value().expect("Unable to get host return value as f32")
136+
}
137+
138+
#[unsafe(no_mangle)]
139+
pub extern "C" fn hl_get_host_return_value_as_Double() -> f64 {
140+
get_host_return_value().expect("Unable to get host return value as f64")
141+
}
142+
143+
#[unsafe(no_mangle)]
144+
pub extern "C" fn hl_get_host_return_value_as_String() -> *const c_char {
145+
let string_value: String =
146+
get_host_return_value().expect("Unable to get host return value as string");
147+
148+
let c_string = CString::new(string_value).expect("Failed to create CString");
149+
c_string.into_raw()
150+
}
151+
152+
#[unsafe(no_mangle)]
153+
pub extern "C" fn hl_get_host_return_value_as_VecBytes() -> Box<FfiVec> {
154+
let vec_value: Vec<u8> =
155+
get_host_return_value().expect("Unable to get host return value as vec bytes");
156+
157+
Box::new(unsafe { FfiVec::from_vec(vec_value) })
158+
}

src/hyperlight_host/tests/common/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,14 @@ pub fn new_uninit_rust() -> Result<UninitializedSandbox> {
3535
)
3636
}
3737

38+
/// Returns a c-language simpleguest.
39+
pub fn new_uninit_c() -> Result<UninitializedSandbox> {
40+
UninitializedSandbox::new(
41+
GuestBinary::FilePath(c_simple_guest_as_string().unwrap()),
42+
None,
43+
)
44+
}
45+
3846
pub fn get_simpleguest_sandboxes(
3947
writer: Option<HostFunction<i32, (String,)>>, // An optional writer to make sure correct info is passed to the host printer
4048
) -> Vec<MultiUseSandbox> {

src/hyperlight_host/tests/integration_test.rs

Lines changed: 93 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use hyperlight_testing::{c_simple_guest_as_string, simple_guest_as_string};
2828
use log::LevelFilter;
2929

3030
pub mod common; // pub to disable dead_code warning
31-
use crate::common::{new_uninit, new_uninit_rust};
31+
use crate::common::{new_uninit, new_uninit_c, new_uninit_rust};
3232

3333
// A host function cannot be interrupted, but we can at least make sure after requesting to interrupt a host call,
3434
// we don't re-enter the guest again once the host call is done
@@ -765,3 +765,95 @@ fn log_test_messages(levelfilter: Option<log::LevelFilter>) {
765765
.unwrap();
766766
}
767767
}
768+
769+
/// Tests whether host is able to return Bool as return type
770+
/// or not
771+
#[test]
772+
fn test_if_guest_is_able_to_get_bool_return_values_from_host() {
773+
let mut sbox1 = new_uninit_c().unwrap();
774+
775+
sbox1
776+
.register("HostBool", |a: i32, b: i32| a + b > 10)
777+
.unwrap();
778+
let mut sbox3 = sbox1.evolve().unwrap();
779+
780+
for i in 1..10 {
781+
if i < 6 {
782+
let res = sbox3
783+
.call::<bool>("GuestRetrievesBoolValue", (i, i))
784+
.unwrap();
785+
println!("{:?}", res);
786+
assert!(!res);
787+
} else {
788+
let res = sbox3
789+
.call::<bool>("GuestRetrievesBoolValue", (i, i))
790+
.unwrap();
791+
println!("{:?}", res);
792+
assert!(res);
793+
}
794+
}
795+
}
796+
797+
/// Tests whether host is able to return Float/f32 as return type
798+
/// or not
799+
/// Adding Ignore attribute, due known issues with float and double
800+
/// calculations - see Github issue #179. Once it is fixed we can
801+
/// remove ignore attribute
802+
#[ignore]
803+
#[test]
804+
fn test_if_guest_is_able_to_get_float_return_values_from_host() {
805+
let mut sbox1 = new_uninit_c().unwrap();
806+
807+
sbox1
808+
.register("HostAddFloat", |a: f32, b: f32| a + b)
809+
.unwrap();
810+
let mut sbox3 = sbox1.evolve().unwrap();
811+
let res = sbox3
812+
.call::<f32>("GuestRetrievesFloatValue", (1.34_f32, 1.34_f32))
813+
.unwrap();
814+
println!("{:?}", res);
815+
assert_eq!(res, 2.68_f32);
816+
}
817+
818+
/// Tests whether host is able to return Double/f64 as return type
819+
/// or not
820+
/// Adding Ignore attribute, due known issues with float and double
821+
/// calculations - see Github issue #179. Once it is fixed we can
822+
/// remove ignore attribute
823+
#[ignore]
824+
#[test]
825+
fn test_if_guest_is_able_to_get_double_return_values_from_host() {
826+
let mut sbox1 = new_uninit_c().unwrap();
827+
828+
sbox1
829+
.register("HostAddDouble", |a: f64, b: f64| a + b)
830+
.unwrap();
831+
let mut sbox3 = sbox1.evolve().unwrap();
832+
let res = sbox3
833+
.call::<f64>("GuestRetrievesDoubleValue", (1.34_f64, 1.34_f64))
834+
.unwrap();
835+
println!("{:?}", res);
836+
assert_eq!(res, 2.68_f64);
837+
}
838+
839+
/// Tests whether host is able to return String as return type
840+
/// or not
841+
#[test]
842+
fn test_if_guest_is_able_to_get_string_return_values_from_host() {
843+
let mut sbox1 = new_uninit_c().unwrap();
844+
845+
sbox1
846+
.register("HostAddStrings", |a: String| {
847+
a + ", string added by Host Function"
848+
})
849+
.unwrap();
850+
let mut sbox3 = sbox1.evolve().unwrap();
851+
let res = sbox3
852+
.call::<String>("GuestRetrievesStringValue", ())
853+
.unwrap();
854+
println!("{:?}", res);
855+
assert_eq!(
856+
res,
857+
"Guest Function, string added by Host Function".to_string()
858+
);
859+
}

src/tests/c_guests/c_simpleguest/main.c

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,80 @@ int guest_function(const char *from_host) {
256256
return 0;
257257
}
258258

259+
bool guest_fn_checks_if_host_returns_bool_value(int32_t a, int32_t b) {
260+
hl_Parameter params[2];
261+
262+
params[0].tag = hl_ParameterType_Int;
263+
params[0].value.Int = a;
264+
265+
params[1].tag = hl_ParameterType_Int;
266+
params[1].value.Int = b;
267+
268+
const hl_FunctionCall host_call = {.function_name = "HostBool",
269+
.parameters = params,
270+
.parameters_len = 2,
271+
.return_type = hl_ReturnType_Bool
272+
};
273+
hl_call_host_function(&host_call);
274+
return hl_get_host_return_value_as_Bool();
275+
}
276+
277+
float guest_fn_checks_if_host_returns_float_value(float a, float b) {
278+
hl_Parameter params[2];
279+
280+
params[0].tag = hl_ParameterType_Float;
281+
params[0].value.Float = a;
282+
283+
params[1].tag = hl_ParameterType_Float;
284+
params[1].value.Float = b;
285+
286+
const hl_FunctionCall host_call = {.function_name = "HostAddFloat",
287+
.parameters = params,
288+
.parameters_len = 2,
289+
.return_type = hl_ReturnType_Float
290+
};
291+
hl_call_host_function(&host_call);
292+
return hl_get_host_return_value_as_Float();
293+
}
294+
295+
double guest_fn_checks_if_host_returns_double_value(double a, double b) {
296+
hl_Parameter params[2];
297+
298+
params[0].tag = hl_ParameterType_Double;
299+
params[0].value.Double = a;
300+
301+
params[1].tag = hl_ParameterType_Double;
302+
params[1].value.Double = b;
303+
304+
const hl_FunctionCall host_call = {.function_name = "HostAddDouble",
305+
.parameters = params,
306+
.parameters_len = 2,
307+
.return_type = hl_ReturnType_Double
308+
};
309+
hl_call_host_function(&host_call);
310+
return hl_get_host_return_value_as_Double();
311+
}
312+
313+
const char* guest_fn_checks_if_host_returns_string_value() {
314+
char guest_message[256] = "Guest Function";
315+
hl_Parameter params;
316+
317+
params.tag = hl_ParameterType_String;
318+
params.value.String = guest_message;
319+
320+
const hl_FunctionCall host_call = {.function_name = "HostAddStrings",
321+
.parameters = &params,
322+
.parameters_len = 1,
323+
.return_type = hl_ReturnType_String
324+
};
325+
hl_call_host_function(&host_call);
326+
return hl_get_host_return_value_as_String();
327+
}
328+
329+
HYPERLIGHT_WRAP_FUNCTION(guest_fn_checks_if_host_returns_float_value, Float, 2, Float, Float)
330+
HYPERLIGHT_WRAP_FUNCTION(guest_fn_checks_if_host_returns_double_value, Double, 2, Double, Double)
331+
HYPERLIGHT_WRAP_FUNCTION(guest_fn_checks_if_host_returns_string_value, String, 0)
332+
HYPERLIGHT_WRAP_FUNCTION(guest_fn_checks_if_host_returns_bool_value, Bool, 2, Int, Int)
259333
HYPERLIGHT_WRAP_FUNCTION(echo, String, 1, String)
260334
// HYPERLIGHT_WRAP_FUNCTION(set_byte_array_to_zero, 1, VecBytes) is not valid for functions that return VecBytes
261335
HYPERLIGHT_WRAP_FUNCTION(guest_function, Int, 1, String)
@@ -289,6 +363,10 @@ HYPERLIGHT_WRAP_FUNCTION(log_message, Int, 2, String, Long)
289363

290364
void hyperlight_main(void)
291365
{
366+
HYPERLIGHT_REGISTER_FUNCTION("GuestRetrievesFloatValue", guest_fn_checks_if_host_returns_float_value);
367+
HYPERLIGHT_REGISTER_FUNCTION("GuestRetrievesDoubleValue", guest_fn_checks_if_host_returns_double_value);
368+
HYPERLIGHT_REGISTER_FUNCTION("GuestRetrievesStringValue", guest_fn_checks_if_host_returns_string_value);
369+
HYPERLIGHT_REGISTER_FUNCTION("GuestRetrievesBoolValue", guest_fn_checks_if_host_returns_bool_value);
292370
HYPERLIGHT_REGISTER_FUNCTION("Echo", echo);
293371
// HYPERLIGHT_REGISTER_FUNCTION macro does not work for functions that return VecBytes,
294372
// so we use hl_register_function_definition directly
@@ -338,4 +416,4 @@ hl_Vec *c_guest_dispatch_function(const hl_FunctionCall *function_call) {
338416
}
339417

340418
return NULL;
341-
}
419+
}

0 commit comments

Comments
 (0)