// lib.rs // // 此部分代码主要负责Rust-C两侧的数据内存结构转换,提供了C侧的函数接口。注意命名规范: // 在C侧使用时,凡是函数名带有 '_cwallet'的,调用过之后都必须用'free_cwallet'释放内存, // 否则导致内存泄漏 // use std::ffi::{CStr, CString}; use std::os::raw::c_char; mod wallet; use wallet_impl::Wallet; use crate::wallet::*; // #[cfg(target_os = "android")] // mod android; macro_rules! cchar_to_str{ ($p1:expr) => { { let s = CStr::from_ptr($p1); let ps = s.to_str().unwrap(); ps } } } macro_rules! ostr_to_cchar{ ($p1:expr) => { { let key = match $p1 { Some(val) => { CString::new(val).unwrap() }, None => CString::new("").unwrap() }; let c_key: *mut c_char = key.into_raw(); c_key } } } #[repr(C)] pub struct CWallet { pub msg_key: *mut c_char, pub master_key: *mut c_char, pub second_key: *mut c_char, pub backup_key: *mut c_char, } #[no_mangle] pub unsafe extern "C" fn new_wallet(msg: *const c_char) -> CWallet { println!("generating wallet"); let str = cchar_to_str!(msg); let rust_wallet = wallet_impl::Wallet::new(str); println!("rust_wallet: {:?}", &rust_wallet); convert_to_cwallet(rust_wallet) } #[no_mangle] pub unsafe extern "C" fn restore_wallet(msg: *const c_char) -> CWallet { println!("generating wallet"); let str = cchar_to_str!(msg); let rust_wallet = wallet_impl::Wallet::new(str); println!("rust_wallet: {:?}", &rust_wallet); convert_to_cwallet(rust_wallet) } #[no_mangle] pub unsafe extern "C" fn free_cwallet(cw: CWallet) { drop(CString::from_raw(cw.msg_key)); drop(CString::from_raw(cw.master_key)); drop(CString::from_raw(cw.second_key)); drop(CString::from_raw(cw.backup_key)); } #[no_mangle] pub unsafe extern "C" fn get_address(cw: CWallet) -> *mut c_char{ let rwallet = convert_to_rwallet(&cw); println!("rwallet: {:?}", rwallet); let address = rwallet.get_address(); let address_str = format!("{:?}", address); let c_address = CString::new(address_str).unwrap(); c_address.into_raw() } unsafe fn convert_to_cwallet(rwallet: Wallet) -> CWallet { // 转换Rust字符串数据为C的字符串并移交ownership let msgkey = CString::new(rwallet.msg_key).unwrap(); let c_msgkey: *mut c_char = msgkey.into_raw(); let masterkey = CString::new(rwallet.master_key).unwrap(); let c_masterkey: *mut c_char = masterkey.into_raw(); let c_secondkey = ostr_to_cchar!(rwallet.second_key); let c_backupkey = ostr_to_cchar!(rwallet.backup_key); let cw = CWallet { msg_key: c_msgkey, master_key: c_masterkey, second_key: c_secondkey, backup_key: c_backupkey, }; cw } unsafe fn convert_to_rwallet(cwallet: &CWallet) -> Wallet { let pmsg = cchar_to_str!(cwallet.msg_key); let pm = cchar_to_str!(cwallet.master_key); let ps = cchar_to_str!(cwallet.second_key); let pb = cchar_to_str!(cwallet.backup_key); Wallet { msg_key: pmsg.to_string(), master_key: pm.to_string(), second_key: Some(ps.to_string()), backup_key: Some(pb.to_string()) } }