如何唯一标识对函数的所有调用?

发布于 2024-09-07 04:48:27 字数 947 浏览 4 评论 0原文

我知道 caller 会给我文件名并且调用函数的行号,但如何获取字符或字节偏移量?如果我必须降到 XS 也没关系(无论如何,该函数最终可能会变成 XS)。

我想做的是唯一地标识对函数的所有调用,因此,如果有比源中的位置更好的方法,我愿意接受其他路线。

基本目的是创建一个可以安全地迭代相同哈希的 each 函数。这是一个纯 Perl 版本,与我正在考虑的类似:

#!/usr/bin/perl

use 5.012;
use warnings;
use Scalar::Util qw/refaddr/;

sub safe_each(\%) {
    my $h    = shift;
    my $key  = join "/", (caller)[1,2], refaddr $h;
    state %iter;

    unless (exists $iter{$key}) {
        $iter{$key} = [ keys %$h ];
    }

    unless (@{$iter{$key}}) {
        delete $iter{$key};
        return;
    }

    my $cur = shift @{$iter{$key}};

    return wantarray ? ($cur, $h->{$cur}) : $cur;
}

my %h = (a => 1, b => 2);
while (my ($k, $v) = safe_each %h) {
    say "$k => $v";
    while (my ($k, $v) = safe_each %h) {
        say "\t$k => $v";
    }
}

I know that caller will give me the file name and line number where a function was called, but how can I get the character or byte offset? It is okay if I must drop down to XS for it (the function will probably wind up being XS anyway).

What I am trying to do is uniquely identify all of the calls to a function, so, if there is a better method than location in the source, I am open to other routes.

The basic intent is to make an each function that can safely iterate over the same hash. Here is a pure Perl version that is similar to what I am thinking about:

#!/usr/bin/perl

use 5.012;
use warnings;
use Scalar::Util qw/refaddr/;

sub safe_each(\%) {
    my $h    = shift;
    my $key  = join "/", (caller)[1,2], refaddr $h;
    state %iter;

    unless (exists $iter{$key}) {
        $iter{$key} = [ keys %$h ];
    }

    unless (@{$iter{$key}}) {
        delete $iter{$key};
        return;
    }

    my $cur = shift @{$iter{$key}};

    return wantarray ? ($cur, $h->{$cur}) : $cur;
}

my %h = (a => 1, b => 2);
while (my ($k, $v) = safe_each %h) {
    say "$k => $v";
    while (my ($k, $v) = safe_each %h) {
        say "\t$k => $v";
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

旧竹 2024-09-14 04:48:28

Perl 调试器将其需要的源文件的所有行加载到条目下的主符号表中。

@::{"_<$path_to_file"}

这样,当您到达文件 FILE 中行 LINE 处的断点时,调试器可以显示您将要执行的代码行:

$::{"_<FILE"}[LINE]

但您也可以使用此信息来计算源文件中的当前字符偏移量。

sub _get_offset_into_file {
    my ($file,$line) = @_;
    my *teh_codez = @::{"_<$file"};

    my $offset = 0;
    # the debugger spoofs line $teh_codez[0], so don't include it in offset calc
    $offset += length $_ for @teh_codez[1 .. $line-1];
    return $offset
}

您可以在调试器下运行代码,或者模拟调试器的功能并自己将文件加载到内存中(这样您就不必使用相同的“_<”+文件名约定,甚至根本不需要使用符号表) )。

抱歉,如果这是一个与您所问的问题完全不同的问题的答案。

The perl debugger loads all lines of the source files that it needs into the main symbol table under the entry

@::{"_<$path_to_file"}

This way when you reach a breakpoint at line LINE in file FILE, the debugger can display the line of code you are about to execute:

$::{"_<FILE"}[LINE]

But you could also use this information to compute the current character offset into your source file.

sub _get_offset_into_file {
    my ($file,$line) = @_;
    my *teh_codez = @::{"_<$file"};

    my $offset = 0;
    # the debugger spoofs line $teh_codez[0], so don't include it in offset calc
    $offset += length $_ for @teh_codez[1 .. $line-1];
    return $offset
}

You could either run your code under the debugger, or emulate what the debugger does and load the files into memory yourself (then you wouldn't have to use the same "_<" + filename convention, or even use the symbol table at all).

Sorry if this is an answer to a completely different question than the one you are asking.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文