Как я могу получить доступ к месту вызова функции каждый раз, когда она вызывается? - PullRequest
1 голос
/ 17 марта 2020

Я хотел бы написать функцию, которая обращается к файлу и номеру строки местоположения, в котором он вызывается.

Это будет выглядеть так:

fn main() {
    prints_calling_location(); // would print `called from line: 2`
    prints_calling_location(); // would print `called from line: 3`
}

fn prints_calling_location() {
    let caller_line_number = /* ??? */;
    println!("called from line: {}", caller_line_number);
}

Ответы [ 2 ]

5 голосов
/ 17 марта 2020

RF C 2091: Неявное местоположение вызывающего абонента добавляет функцию track_caller, которая позволяет функции получить доступ к местоположению своего вызывающего абонента.

Краткий ответ: для получения местоположения, в котором вызывается ваша функция, пометьте его #[track_caller] и используйте std::panic::Location::caller в своем теле.

Исходя из этого ответ, ваш пример будет выглядеть так:

#![feature(track_caller)]

fn main() {
    prints_calling_location(); // would print `called from line: 2`
    prints_calling_location(); // would print `called from line: 3`
}

#[track_caller]
fn prints_calling_location() {
    let caller_location = std::panic::Location::caller();
    let caller_line_number = caller_location.line();
    println!("called from line: {}", caller_line_number);
}

игровая площадка

Более конкретно, функция std::panic::Location::caller имеет два поведения:

  • Внутри функции, помеченной #[track_caller], он возвращает &'static Location<'static>, который вы можете использовать, чтобы узнать файл, номер строки и номер столбца, в котором ваша функция получает call.
  • Внутри функции, которая не имеет #[track_caller], она подвержена ошибкам и возвращает фактическое местоположение, где вы ее вызвали, а не то, где вызывается ваша функция, для Например:

    #![feature(track_caller)]
    
    fn main() {
        oops();
        // ^ prints `line: 10` instead of the expected `line: 4`
    }
    
    // note: missing #[track_caller] here
    fn oops() {
        println!("line: {}", std::panic::Location::caller().line());
    }
    

    ссылка на игровую площадку

2 голосов
/ 17 марта 2020

Альтернативой использованию «Неявного местоположения вызывающего абонента» (который может быть недоступен / не подходит вам по какой-либо причине) является выполнение действий C. Т.е. скрыть свою функцию за макросом.

macro_rules! prints_calling_location {
    () => { 
        let caller_line_number = line!();
        println!("called from line: {}", caller_line_number);
    };
}

fn main() {
    prints_calling_location!(); // prints `called from line: 10`
    prints_calling_location!(); // prints `called from line: 11`
}

ссылка на игровую площадку

...