2015-06-19 14 views
5

Tôi đang cố gắng sử dụng macro mà tôi đã tạo trong một mô-đun riêng biệt. Với tham chiếu đến this SO question, tôi đã nhập tiền phạt macro. Tuy nhiên có vẻ như rằng tôi cóTại sao tôi phải phơi bày 'sử dụng' của macro trong thư viện khách hàng?

Update để thêm thi hành vĩ mô

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())) 
      } 
     } 

    } 
} 

và main.rs trong một thùng riêng

// 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"); 
} 

này hoạt động tốt, nhưng use std::* dòng là tất cả các phần của việc triển khai trong lib.rs.

Tại sao tôi phải để lộ 'sử dụng' của triển khai trong thư viện khách hàng? Không nên rỉ sét như là một phần của nó mở rộng 'bao gồm' bất cứ điều gì là trong lib.rs?

Trả lời

5

macro_rules! có số lượng hơi thấp hơn bạn mong đợi. Ví dụ, nó không mang lại nhập khẩu với nó khi nó mở rộng một cái gì đó. Tốt nhất là hãy nghĩ đến việc mở rộng macro là chủ yếu là chỉ là một công việc sao chép cùn + dán.

Nếu bạn xem bất kỳ macro được viết hợp lý nào phụ thuộc vào biểu tượng bên ngoài, bạn sẽ thấy những thứ như ::std::result::Result thay vì Result. Điều này là do trình ghi macro không thể phụ thuộc vào Result có nghĩa là những gì họ mong đợi trong ngữ cảnh mở rộng. Vì vậy, bước đầu tiên là để đủ điều kiện đường dẫn hoàn toàn. Điều quan trọng cần biết là mọi mở rộng macro đều được thay thế $crate là đường dẫn đến thùng trong đó macro được xác định. Bạn có thể sử dụng quyền truy cập này để truy cập, ví dụ: DbaxError$crate::DbaxError.

Cuối cùng, bạn đang gặp may; với việc mở rộng, bạn có thể ăn gian một chút và chỉ cần thêm use các mục vào bên trong mở rộng:

#[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) }; 
      // ... 
     } 
    } 
} 
Các vấn đề liên quan