小天管理 发表于 10月7日 发表于 10月7日 新人学习 rust ffi ,实在搞不定,特来请教一下 下面段代码主要是实现一个简单的字符串然后通过 FFI 调用 hyperscan (这是一个 C++写的库,我通过 lib 调用,完全静态编译)的正则表达式同时匹配多个 pattern ,然后打印每一个 pattern 出现的第一个位置即可,如果没出现打印-1 。 但是这个代码我怎么改都是-1 或者 0 ,就是不能有正确结果,我问了多个 AI ,但是都始终无法解决这个问题,所以想向大神请教一下,非常感谢。 运行结果如下: Hyperscan 版本: 5.4.2 2024-10-06 模式 "test" 未出现,位置: -1 模式 "string" 未出现,位置: -1 模式 "example" 未出现,位置: -1 模式 "中文" 未出现,位置: -1 完整代码如下: use std::ffi::{CStr, CString}; use std::os::raw::{c_int, c_uint, c_void}; use std::ptr; const HS_MODE_BLOCK: c_uint = 1; const HS_FLAG_LITERAL: c_uint = 1 << 10; // 添加 HS_FLAG_LITERAL 常量 #[link(name = "hs")] extern "C" { fn hs_version() -> *const i8; pub fn hs_compile_multi( expressions: *const *const i8, flags: *const c_uint, ids: *const c_uint, elements: c_uint, mode: c_uint, platform: *const c_void, db: *mut *mut hs_database_t, compile_err: *mut *mut hs_compile_error_t, ) -> c_int; pub fn hs_alloc_scratch( db: *const hs_database_t, scratch: *mut *mut hs_scratch_t, ) -> c_int; pub fn hs_free_scratch( scratch: *mut hs_scratch_t, ) -> c_int; pub fn hs_scan( db: *const hs_database_t, data: *const i8, length: c_uint, flags: c_uint, scratch: *mut hs_scratch_t, match_event_handler: Option< extern "C" fn( id: c_uint, from: u64, to: u64, flags: c_uint, context: *mut c_void, ) -> c_int, >, context: *mut c_void, ) -> c_int; pub fn hs_free_database(db: *mut hs_database_t) -> c_int; pub fn hs_free_compile_error(error: *mut hs_compile_error_t); } pub enum hs_database_t {} pub enum hs_scratch_t {} #[repr(C)] pub struct hs_compile_error_t { pub message: *const i8, pub expression: c_int, } const HS_SUCCESS: c_int = 0; extern "C" fn event_handler( id: c_uint, from: u64, _to: u64, _flags: c_uint, context: *mut c_void, ) -> c_int { unsafe { let positions = context as *mut u64; let pos_ptr = positions.add(id as usize); if *pos_ptr == u64::MAX { *pos_ptr = from; } } 0 } fn main() { unsafe { // 获取并打印 Hyperscan 版本 let version = hs_version(); let c_str = CStr::from_ptr(version); let str_slice = c_str.to_str().unwrap(); println!("Hyperscan 版本: {}", str_slice); // 定义要匹配的模式列表 let patterns = vec!["test", "string", "example", "中文"]; // 将模式转换为 CString let c_patterns: Vec<CString> = patterns .iter() .map(|s| CString::new(*s).unwrap()) .collect(); // 创建 expressions 、flags 、ids 数组 let expressions: Vec<*const i8> = c_patterns.iter().map(|s| s.as_ptr()).collect(); // 使用 HS_FLAG_LITERAL 标志 let flags: Vec<c_uint> = vec![HS_FLAG_LITERAL; patterns.len()]; let ids: Vec<c_uint> = (0..patterns.len() as c_uint).collect(); // 编译模式 let mut db: *mut hs_database_t = ptr::null_mut(); let mut compile_err: *mut hs_compile_error_t = ptr::null_mut(); let compile_result = hs_compile_multi( expressions.as_ptr(), flags.as_ptr(), ids.as_ptr(), patterns.len() as c_uint, HS_MODE_BLOCK, ptr::null(), &mut db, &mut compile_err, ); if compile_result != HS_SUCCESS { if !compile_err.is_null() { let err = &*compile_err; let message = CStr::from_ptr(err.message).to_string_lossy(); println!("编译错误: {}", message); hs_free_compile_error(compile_err); } else { println!("未知的编译错误"); } return; } // 分配 scratch 空间 let mut scratch: *mut hs_scratch_t = ptr::null_mut(); let alloc_result = hs_alloc_scratch(db, &mut scratch); if alloc_result != HS_SUCCESS { println!("hs_alloc_scratch 失败"); hs_free_database(db); return; } // 定义输入字符串 let input = "This is a test string for example purposes 中文测试."; // 初始化匹配位置数组 let mut match_positions: Vec<u64> = vec![u64::MAX; patterns.len()]; // 执行扫描 let scan_result = hs_scan( db, input.as_ptr() as *const i8, input.len() as c_uint, 0, scratch, Some(event_handler), match_positions.as_mut_ptr() as *mut c_void, ); if scan_result != HS_SUCCESS { println!("hs_scan 失败,错误代码: {}", scan_result); hs_free_scratch(scratch); hs_free_database(db); return; } // 输出结果 for (i, pattern) in patterns.iter().enumerate() { let pos = match_positions[i]; if pos != u64::MAX { println!("模式 \"{}\" 首次出现位置: {}", pattern, pos); } else { println!("模式 \"{}\" 未出现,位置: -1", pattern); } } // 释放资源 hs_free_scratch(scratch); hs_free_database(db); } }
已推荐帖子
创建帐户或登录来提出意见
您需要成为会员才能提出意见
创建帐户
注册成为会员.只要几个简单步骤!
注册帐户登录
已经有帐户? 请在此处登录.
现在登录