Skip to content

Commit 3e03029

Browse files
committed
Implement 1-slotted Foreign objects
(temporary?) solution to #4 ... #4 (comment)
1 parent 33121f5 commit 3e03029

File tree

12 files changed

+360
-124
lines changed

12 files changed

+360
-124
lines changed

src/lib.rs

Lines changed: 105 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,12 @@ mod tests {
4646
pub use scm::*;
4747
pub use std::string::String;
4848
pub use interp::Guile;
49+
pub use guile_rs_sys::{SCM, scm_t_subr, scm_c_define_gsubr};
4950

5051
use std;
5152
use std::thread;
5253
use std::marker::PhantomData;
54+
use std::ffi::CString;
5355

5456
#[test]
5557
pub fn guile_test() {
@@ -130,54 +132,119 @@ mod tests {
130132
scm_eval!{ "test" }
131133
}, ()).unwrap().equal_p(&Scm::<ScmString>::from("test")).is_true());
132134

133-
#[allow(dead_code)]
134-
struct TestStruct {
135-
val1: u8
136-
}
137135

136+
}, ());
137+
138+
let _ = Guile::call_with_guile(|_| {
139+
Guile::eval("(define h (make-hash-table 32))");
140+
Guile::eval(r#"(hashq-set! h 'foo "bar")"#);
141+
}, ());
142+
}
143+
144+
#[test]
145+
pub fn foreign_test() {
146+
#[allow(dead_code)]
147+
#[derive(Debug)]
148+
struct TestStruct {
149+
data0: u8
150+
}
151+
152+
153+
lazy_static! {
154+
// static ref FTYPE: Scm<Foreign> = {
155+
// Guile::call_with_guile(|_| {
156+
// Scm::new_type(&"Test".into(), &vec![Scm::<ScmString>::from("val1")].into(), type_list![TestStruct])
157+
// }, ())
158+
// };
159+
// static ref FSLOTS: Box<TypeList> = type_list![TestStruct];
160+
//
161+
static ref FTYPE: Scm<Foreign<TestStruct>> = {
162+
Guile::call_with_guile(|_| {
163+
Scm::new_type(&"Test".into())
164+
}, ())
165+
};
166+
}
167+
168+
// struct TestType {}
169+
// impl ForeignSpec for TestType {
170+
// // type SlotTypes = type_list![TestStruct];
171+
172+
unsafe extern "C" fn test_data(fo: SCM) -> SCM {
173+
let st = Scm::<Untyped>::from_raw(fo).into_foreign(&*FTYPE).unwrap();
174+
assert!(st.is_foreign(&*FTYPE));
175+
176+
if st.get_data().unwrap().data0 == 32 {
177+
Scm::true_c()
178+
} else {
179+
Scm::false_c()
180+
}.into_raw()
181+
}
182+
183+
unsafe extern "C" fn get_foreign_o(n: SCM) -> SCM {
184+
let n: u8 = Scm::<Untyped>::from_raw(n).into_integer().unwrap().try_as().unwrap();
185+
186+
let st = Scm::<ForeignObject<TestStruct>>::new(&*FTYPE, TestStruct { data0: n });
187+
188+
st.into_raw()
189+
}
190+
191+
let st = Scm::<ForeignObject<TestStruct>>::new(&*FTYPE, TestStruct { data0: 21 });
138192

139-
lazy_static! {
140-
static ref FTYPE: Scm<Foreign> = {
141-
Guile::call_with_guile(|_| {
142-
Scm::new_type(&"Test".into(), &vec![Scm::<ScmString>::from("val1")].into(), type_list![TestStruct])
143-
}, ())
144-
};
145-
static ref FSLOTS: Box<TypeList> = type_list![TestStruct];
146-
}
147193

148-
struct TestType { }
149-
impl ForeignSpec for TestType {
150-
type Struct = TestStruct;
151-
fn get_type<'a>() -> &'a Scm<Foreign> { &FTYPE }
152-
fn get_slot_types() -> Box<TypeList> {
153-
// Box clone clones the boxes contents
154-
FSLOTS.clone()
155-
}
156-
fn as_struct_mut<'a>() -> &'a mut Self::Struct {
157-
unimplemented!()
158-
// &mut TestStruct { val1: 7 }
159-
}
160-
fn as_struct<'a>() -> &'a Self::Struct {
161-
// This should actually pull it from the SCM data...
162-
163-
// Dummy:
164-
&TestStruct { val1: 7 }
165-
}
194+
let _ = Guile::call_with_guile(|_| {
195+
unsafe {
196+
let _ = scm_c_define_gsubr(
197+
CString::new("test-data").unwrap().as_ptr(),
198+
1, 0, 0,
199+
test_data as scm_t_subr
200+
);
201+
202+
let _ = scm_c_define_gsubr(
203+
CString::new("get-foreign-o").unwrap().as_ptr(),
204+
1, 0, 0,
205+
get_foreign_o as scm_t_subr
206+
);
166207
}
167208

168-
//type TestTypeSpec = ForeignObject<TestType>;
209+
assert!(st.is_foreign(&*FTYPE));
210+
assert_eq!(st.get_data().unwrap().data0, 21u8);
169211

170-
// NOTE: this commented test makes no sense anymore
171-
// let st: Scm<TestTypeSpec>
172-
// = Scm::from_struct(TestStruct { val1: 21 });
212+
let res: Scm<Untyped> = Guile::eval("
173213
214+
(test-data (get-foreign-o 32))
174215
175-
}, ());
216+
");
217+
218+
assert!(res.is_true())
176219

177-
let _ = Guile::call_with_guile(|_| {
178-
Guile::eval("(define h (make-hash-table 32))");
179-
Guile::eval(r#"(hashq-set! h 'foo "bar")"#);
180220
}, ());
221+
222+
// // fn get_type<'a>() -> &'a Scm<Foreign> { &FTYPE }
223+
// // fn get_slot_types() -> Box<TypeList> {
224+
// // // &FTYPE.get_slot_types()
225+
// // // Box clone clones the boxes contents
226+
// // FSLOTS.clone()
227+
// // }
228+
// // fn as_struct_mut<'a>() -> &'a mut Self::Struct {
229+
// // unimplemented!()
230+
// // // &mut TestStruct { val1: 7 }
231+
// // }
232+
// // fn as_struct<'a>() -> &'a Self::Struct {
233+
// // // This should actually pull it from the SCM data...
234+
235+
// // // Dummy:
236+
// // &TestStruct { val1: 7 }
237+
// // }
238+
// }
239+
240+
//type TestTypeSpec = ForeignObject<TestType>;
241+
242+
// NOTE: this commented test makes no sense anymore
243+
// let st: Scm<TestTypeSpec>
244+
// = Scm::from_struct(TestStruct { val1: 21 });
245+
246+
// let _ = Guile::call_with_guile(|_| {}, ());
247+
181248
}
182249

183250
#[test]

src/scm/bool.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use scm::TypeSpec;
66
use guile_rs_sys::*;
77

88

9-
#[derive(Debug)]
9+
#[derive(Clone, Debug)]
1010
pub struct Bool;
1111
impl TypeSpec for Bool {}
1212

0 commit comments

Comments
 (0)