为什么我必须在客户端库中公开宏实现的 '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) };
// ...
}
}
}
我正在尝试使用我在单独模块中创建的宏。参考
更新以添加宏实现
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) };
// ...
}
}
}