在XS中,有没有一种方法可以访问Perl中的特殊标记?

10
在Perl中,存在像__PACKAGE____SUB____FILE____LINE__这样的特殊标记,并可从脚本中使用。
我可以从XS中获取__PACKAGE__的值,例如HvNAME(PL_currstash),但是如何访问其他的呢?
是否有专门的接口可以从XS中访问它们?比如:CTX->packageCTX->sub等。

在Perl中,您可以编写C代码。为了简化C<->Perl交互,存在XS机制。我想知道如何从XS访问令牌__SUB__ - Eugen Konkov
在书籍Perl开发者词典的第267页上提到,标记__LINE____FILE__会在编译时被替换。更多详情请参见此处 - Håkon Hægland
正如@HåkonHægland所说,__LINE____FILE__在编译时被替换。然而,当出现die时,您仍然应该能够获取有关行或文件的信息,因为Perl会告诉您发生在哪一行/文件。我建议您查看Perl源代码,特别是当出现die(例如由于除以0)时会发生什么。不确定它是否会显示您要查找的内容,但这就是我会做的方式。 - Dada
@Dada 我相信__FILE____LINE__存储在COP(PL_curcop/PL_op)中。 __SUB__可以通过OP->cv->name访问... 问题不在于如何访问这些数据,而是通过一些特殊接口来访问这些数据。 - Eugen Konkov
4
这些是Perl运算符,因此您只能在Perl代码中调用它们。但是,您肯定可以找到调用您的XS子例程的语句的文件和行号,因为caller可以实现这一点。 - ikegami
显示剩余3条评论
3个回答

3
你可以在 toke.c 中逐个查找编译时的值:
  • __PACKAGE__ => HvNAME(PL_curstash)PL_curstname
  • __FILE__ => CopFILE(PL_curcop) (在编译时)
  • __LINE__ => CopLINE(PL_curcop) (在编译时)
  • __SUB__ => PL_compcv
如果你需要在运行时使用它们,请查看上下文 caller_cx 和当前子程序 (cv) 中可用的各种数据字段。没有像 Parrot 或 Perl6 一样传递的上下文结构,而是一个活动上下文块的堆栈。

2

Perl子例程在C中用类型CV表示。 XSUB的CV通过cv参数传递:

#define XSPROTO(name) void name(pTHX_ CV* cv)

您可以使用GvNAME(CvGV(cv))来获取XSUB的名称。如果您在多个名称下注册了XSUB,例如使用ALIASINTERFACE关键字或者在类型映射中,这将特别有用。

要获取当前存储区(等同于__PACKAGE__),建议使用CvSTASH(cv)

__FILE____LINE__是由C编译器提供的宏。


2

__FILE__的C语言等价物是__FILE__

__LINE__的C语言等价物是__LINE__

C99中__SUB__的等价物是__func__。在此之前没有任何标准。

C语言没有命名空间,因此没有__PACKAGE__的C语言等价物。

话虽如此,我认为你需要的不是关于当前执行行的信息;而是想要XS子程序的调用者信息。这意味着你实际上正在寻找caller的XS等价物。

caller_cxcaller的XS等价物。查看scope.c中的Perl_cx_dump应该可以了解如何使用返回的PERL_CONTEXT结构。


你为什么要发布一个复制粘贴的答案,直接从你之前的回答中复制过来的? - Hovercraft Full Of Eels
那么,对你来说,最好弄清楚哪个应该关闭,并对此进行投票,不是吗?或者至少发表一条评论,链接到你之前的答案,因为复制粘贴答案并不被认为是正确的做法——至少在我看到管理员处理这种情况时(他们有软件可以识别这一点),他们通常会删除一个或两个答案。 - Hovercraft Full Of Eels
@Hovercraft Full Of Eels,我在回答另一个问题时不知道这个问题。 - ikegami
@Hovercraft Full Of Eels,另一个问题将被关闭为重复,但我不会匆忙将一个没有答案的问题作为重复问题关闭。 - ikegami
@rurban, 真的吗???那是一个非常苛刻的评估。已修复以使用更精确的措辞。 - ikegami
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接