跳转到内容
View in the app

A better way to browse. Learn more.

彼岸论坛

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.
欢迎抵达彼岸 彼岸花开 此处谁在 -彼岸论坛

[Rust] RUST 调用 C++的 lib 请教

发表于

新人学习 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);
    }
}

Featured Replies

No posts to show

创建帐户或登录来提出意见

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.