为什么我必须在客户端库中公开宏实现的 'use'?

Why do I have to expose a macro implementation's 'use' in the client library?

我正在尝试使用我在单独模块中创建的宏。参考,我导入了一个宏就好了。不过我好像有

更新以添加宏实现

lib.rs

#![macro_use]
use std::fmt;
use std::ffi::CString;
use std::ffi::CStr;
use std::str;
extern crate libc;

pub enum DbaxError {
    DBAXException(String)
}

 #[macro_export]
macro_rules! dbax_call_test {
    ( $func : expr ) => {
        {
            let call_c_func = unsafe { dbax_function(CString::new($func).unwrap().as_ptr(),0) };
            match unsafe { getErrorCode() as i32 } {
                0 => Ok("Done".to_owned() + $func),
                _ => Err(DbaxError::DBAXException( str::from_utf8(unsafe { CStr::from_ptr(getError()) }.to_bytes()).unwrap().to_string()))
            }
        }

    }
}

和main.rs在一个单独的板条箱中

// Import macro
#[macro_use] extern crate rustdbax;
// Import implementation details of macro
use rustdbax::*;
use std::ffi::CString;
use std::ffi::CStr;
use std::str;

fn main() {
    // Call my macro
    dbax_call_test!("DateAdd");
}

这很好用,但是 use std::* 行都是 lib.rs.

中实现的一部分

为什么我必须在客户端库中公开实现的 'use'? rustc 不应该作为扩​​展的一部分 'include' lib.rs 中的任何内容吗?

因为 macro_rules! 比您想象的要笨一点。例如,当它扩展某些东西时,它不会带来进口。最好将宏扩展视为主要只是一个愚蠢的复制+粘贴工作。

如果您查看任何依赖于外部符号的合理编写的宏,您会看到类似 ::std::result::Result 而不是 Result 的内容。这是因为宏编写者不能依赖 Result 表示他们在扩展上下文中的期望。所以第一步是绝对限定路径。

要知道的第二件事是,每个宏扩展都会得到一个 $crate 替换,这是定义宏的包的路径。您可以使用它来访问,例如,DbaxError 作为 $crate::DbaxError.

终于,你走运了;鉴于扩展,你可以作弊一点,只需添加 use 项目 inside 扩展:

#[macro_export]
macro_rules! dbax_call_test {
    ($func: expr) => {
        {
            use std::ffi::CString;
            use $crate::dbax_function;
            let call_c_func = unsafe { dbax_function(CString::new($func).unwrap().as_ptr(),0) };
            // ...
        }
    }
}