【问题标题】:Perl: Convert string to reference? [duplicate]Perl:将字符串转换为引用? [复制]
【发布时间】:2011-05-19 02:08:46
【问题描述】:

可能重复:
How can I convert the stringified version of array reference to actual array reference in Perl?

我将“SCALAR(0x8ec3a94)”作为文字字符串。我可以强制 Perl 把它变成一个参考然后跟着它?

IE,告诉 Perl:“查看内存位置 0x8ec3a94,然后处理 什么是标量?

相关:Perl: Unwrapping list inside-out doesn't work?

是的,我意识到这是一件可怕的事情。

【问题讨论】:

  • 相关:stackoverflow.com/questions/1671281/…。严格来说不是一个骗局,因为那是关于阵列的。
  • 不,引用不是指针。它最初是如何变成字符串的?这就是错误所在。
  • @shawnhcorey,不,它不是指针,但它包含相同的信息,请参阅我的回答
  • 不,引用不是指针。如果你把它当做一个,你会创造一大堆额外的工作,没人会理解,也无法维护。我的问题仍然存在:它最初是如何变成标量的?这就是 OP 出错的地方。
  • And yes, I realize this is a horrible thing to do. 我相信他的话。让他继续沿着这条黑暗的道路前进,只要他承诺永远不会向世界释放任何这种恶意。

标签: perl coding-style


【解决方案1】:

从 Andy 提供的链接中,尝试Inline::C approach。你会想要使用SV* 而不是AV*,但它应该可以工作。

我已经模拟了一个示例,扩展了该链接中显示的方法。由于我对 C 的了解有限,我认为当引用不再指向任何内容时,我已经阻止了 Segfault(通过取消注释内括号进行测试,允许 $text 超出范围)。因为我在 C 部分使用了newRV_inc,所以$text 的引用计数增加了。因此,如果 $text 超出范围,但其找到的引用 ($recovered_ref) 仍然存在,则该值仍然可用,如预期的那样(通过取消注释外部大括号进行测试)。

这种方法似乎适用于任何类型的参考。不确定对象,如果需要,请尝试一下。要了解更多信息,perldoc Inline::C 会有所帮助,但您需要阅读 perldoc perlguts 甚至可能是 perldoc perlapi 才能继续这条道路。

#!/usr/bin/perl

use strict;
use warnings;

use Inline 'C';

my $stringified_ref_text;
my $stringified_ref_array;
my $recovered_ref_text;
my $recovered_ref_array;

#{
  #{
    my $text = "Hello World";
    my @array = qw"Hello World!";

    $stringified_ref_text = \$text . "";
    $stringified_ref_array = \@array . "";

    print $stringified_ref_text . "\n";
    print $stringified_ref_array . "\n";
  #}

  $recovered_ref_text = recover_ref($stringified_ref_text);
  $recovered_ref_array = recover_ref($stringified_ref_array);
#}

print $$recovered_ref_text . "\n";
print "$_\n" for @$recovered_ref_array;

sub recover_ref {

  my $input = shift;

  my $addr;
  if ($input =~ /0x(\w+)/) {
    $addr = hex($1);
  } else {
    warn "Could not find an address";
    return undef;
  }
  my $ref = _recover_ref($addr) or undef;

  return $ref;
}

__DATA__
__C__

SV* _recover_ref(int address) { 
  if (address) 
    return newRV_inc((SV*) address);

  return 0;
}

【讨论】:

  • 默认情况下,StackOverflow 显示按分数排序的答案,然后(显然)随机解决平局。这意味着您所指的链接可能出现在您的答案下方,或者(在有更多活动的问题中)出现在您上方的几个位置,中间有其他链接。因此,如果您想让人们知道您指的是哪个链接,请不要将其称为“上面的链接”。
  • @Dave,它与我发布的链接相同,只是我指向内部的特定答案。我应该发布两个指向同一个问题的链接吗?这应该可以。
  • 我一直在等待一个简单的理由来学习为 CPAN 制作和打包一个 XS 模块(几天前我刚刚发布了我的第一个纯 Perl 模块)。这是人们在 CPAN 上想要的吗?这会给我一个尝试的理由。
  • @Joel:是的。在 CPAN 上欢迎 Acme::* 之类的东西。这甚至可能很有用。
  • @Tim,感谢您的鼓励,寻找 Acme::RecoverReference,即将来到您附近的 CPAN 镜像
【解决方案2】:

你可以得到最接近的是Tie::RefHash。穷人的版本在哈希中填充引用

$registry{"$ref"} = $ref;

以后再拿出来

print ${ $registry{"SCALAR(0x8ec3a94)"} }, "\n";

这种方法有很多缺点。为什么要这样做?

【讨论】:

  • 我正在尝试“从里到外”解析一些东西,从最里面的引用开始,然后逐步解决。
猜你喜欢
  • 2017-01-06
  • 2014-07-07
  • 2012-11-20
  • 2021-05-01
  • 2014-08-05
  • 1970-01-01
  • 1970-01-01
  • 2020-08-16
相关资源
最近更新 更多