use libc::{c_int, size_t}; use std::ffi::{CStr, CString}; use std::mem; use std::os::raw::c_void; use std::path::Path; use tensorflow_sys as ffi; macro_rules! nonnull( ($pointer:expr) => ({ let pointer = $pointer; assert!(!pointer.is_null()); pointer }); ); macro_rules! ok( ($status:expr) => ({ if ffi::TF_GetCode($status) != ffi::TF_OK { panic!("{}", CStr::from_ptr(ffi::TF_Message($status)).to_string_lossy().into_owned()); } }); ); #[cfg_attr(feature = "examples_system_alloc", global_allocator)] #[cfg(feature = "examples_system_alloc")] static ALLOCATOR: std::alloc::System = std::alloc::System; fn main() { use std::mem::size_of; use std::ptr::{null, null_mut}; use std::slice::from_raw_parts; unsafe { let options = nonnull!(ffi::TF_NewSessionOptions()); let status = nonnull!(ffi::TF_NewStatus()); let graph = nonnull!(ffi::TF_NewGraph()); let graph_def = read("examples/assets/multiplication.pb"); // c = a * b let opts = nonnull!(ffi::TF_NewImportGraphDefOptions()); let graph_def_buf = ffi::TF_Buffer { data: graph_def.as_ptr() as *const c_void, length: graph_def.len(), data_deallocator: None, }; ffi::TF_GraphImportGraphDef(graph, &graph_def_buf, opts, status); ffi::TF_DeleteImportGraphDefOptions(opts); ok!(status); let session = nonnull!(ffi::TF_NewSession(graph, options, status)); let mut inputs = vec![]; let mut input_tensors: Vec<*mut ffi::TF_Tensor> = vec![]; let name = CString::new("a").unwrap(); let mut data = vec![1f32, 2.0, 3.0]; let dims = vec![data.len() as i64]; let input_tensor1 = nonnull!(ffi::TF_NewTensor( ffi::TF_FLOAT, dims.as_ptr(), dims.len() as c_int, data.as_mut_ptr() as *mut _, data.len() as size_t * mem::size_of::(), Some(noop), null_mut() )); let input_op = nonnull!(ffi::TF_GraphOperationByName(graph, name.as_ptr())); inputs.push(ffi::TF_Output { oper: input_op, index: 0, }); input_tensors.push(input_tensor1); let name = CString::new("b").unwrap(); let mut data = vec![4f32, 5.0, 6.0]; let dims = vec![data.len() as i64]; let input_tensor2 = nonnull!(ffi::TF_NewTensor( ffi::TF_FLOAT, dims.as_ptr(), dims.len() as c_int, data.as_mut_ptr() as *mut _, data.len() as size_t as size_t * mem::size_of::(), Some(noop), null_mut() )); let input_op = nonnull!(ffi::TF_GraphOperationByName(graph, name.as_ptr())); inputs.push(ffi::TF_Output { oper: input_op, index: 0, }); input_tensors.push(input_tensor2); let mut outputs = vec![]; let mut output_tensors = vec![]; let name = CString::new("c").unwrap(); let output_op = nonnull!(ffi::TF_GraphOperationByName(graph, name.as_ptr())); outputs.push(ffi::TF_Output { oper: output_op, index: 0, }); output_tensors.push(null_mut()); let mut target_names = vec![]; ffi::TF_SessionRun( session, null(), inputs.as_mut_ptr(), input_tensors.as_ptr(), inputs.len() as c_int, outputs.as_mut_ptr(), output_tensors.as_mut_ptr(), outputs.len() as c_int, target_names.as_mut_ptr(), target_names.len() as c_int, null_mut(), status, ); ok!(status); let output_tensor = nonnull!(output_tensors[0]); let data = nonnull!(ffi::TF_TensorData(output_tensor)) as *const f32; let data = from_raw_parts( data, ffi::TF_TensorByteSize(output_tensor) / size_of::(), ); assert_eq!(data, &[1.0 * 4.0, 2.0 * 5.0, 3.0 * 6.0]); ffi::TF_CloseSession(session, status); ffi::TF_DeleteSession(session, status); ffi::TF_DeleteGraph(graph); ffi::TF_DeleteTensor(output_tensor); ffi::TF_DeleteTensor(input_tensor1); ffi::TF_DeleteTensor(input_tensor2); ffi::TF_DeleteStatus(status); ffi::TF_DeleteSessionOptions(options); } unsafe extern "C" fn noop( _: *mut std::os::raw::c_void, _: size_t, _: *mut std::os::raw::c_void, ) { } } fn read>(path: T) -> Vec { use std::fs::File; use std::io::Read; let mut buffer = vec![]; let mut file = File::open(path).unwrap(); file.read_to_end(&mut buffer).unwrap(); buffer }