简体   繁体   English

如何从 XSUB 设置 Perl 环境变量?

[英]How to set a Perl environment variable from an XSUB?

I am trying to set a Perl environment variable from an XSUB.我正在尝试从 XSUB 设置 Perl 环境变量。 I want it to take immediate effect before the XSUB exits.我希望它在 XSUB 退出之前立即生效。 Here is my XS file, Module.xs :这是我的 XS 文件Module.xs

#define PERL_NO_GET_CONTEXT
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"

MODULE = My::Module  PACKAGE = My::Module
PROTOTYPES: DISABLE

void
set_env_test()
    CODE:
        I32 croak_on_error = 1;
        eval_pv("$ENV{PERL_MEM_LOG}='ms'", croak_on_error);
        printf("C1: getenv : %s\n", getenv("PERL_MEM_LOG"));
        printf("C1: PerlEnv_getenv : %s\n", PerlEnv_getenv("PERL_MEM_LOG"));
        my_setenv("PERL_MEM_LOG", "s");
        printf("C2: getenv : %s\n", getenv("PERL_MEM_LOG"));
        printf("C2: PerlEnv_getenv : %s\n", PerlEnv_getenv("PERL_MEM_LOG"));

and here is a Perl script that uses the XSUB:这是一个使用 XSUB 的 Perl 脚本:

use feature qw(say);
use strict;
use warnings;
use ExtUtils::testlib;
use My::Module;

{
    say "Before: ", get_env();
    My::Module::set_env_test();
    say "After: ", get_env();
}

sub get_env {
    if (exists $ENV{PERL_MEM_LOG}) {
        return $ENV{PERL_MEM_LOG};
    }
    else {
        return "undef";
    }
}

The output is:输出是:

Before: undef
C1: getenv : ms
C1: PerlEnv_getenv : ms
C2: getenv : s
C2: PerlEnv_getenv : s
After: ms

I would like to know if it is possible to set the environment variable without using eval_pv() ?我想知道是否可以在不使用eval_pv()情况下设置环境变量? Is there a specific API function that I can use?是否有我可以使用的特定 API 函数?

Observations:观察:

  • eval_pv() works as expected, eval_pv()按预期工作,
  • my_setenv() works locally and supersedes the value set by eval_pv() until the XSUB exits, then the old value is restored. my_setenv()在本地工作并取代由eval_pv()设置的值,直到 XSUB 退出,然后恢复旧值。
  • my_setenv() cannot be used to set the Perl environment variable permanently, its effect only lasts within the XSUB. my_setenv()不能用于永久设置 Perl 环境变量,其作用仅在 XSUB 内持续。
  • getenv() and PerlEnv_getenv() seems to do the same thing (?) getenv()PerlEnv_getenv()似乎做同样的事情(?)

I don't know why my_setenv doesn't work (since $ENV{PERL_MEM_LOG} = "abc"; ends up calling my_setenv ), but the following does:我不知道为什么my_setenv不起作用(因为$ENV{PERL_MEM_LOG} = "abc";最终调用my_setenv ),但以下内容确实如此:

HV *env_hv = get_hv("ENV", 0);
if (!env_hv)
   croak("wut");

SV **svp = hv_fetchs(env_hv, "PERL_MEM_LOG", 1);
sv_setpvs_mg(*svp, "s");

Test:测试:

use 5.014;
use warnings;

use Inline C => <<'__EOS__';

    void set_env_test() {
        I32 croak_on_error = 1;
        eval_pv("$ENV{PERL_MEM_LOG}='ms'", croak_on_error);
        printf("C1: getenv : %s\n", getenv("PERL_MEM_LOG"));
        printf("C1: PerlEnv_getenv : %s\n", PerlEnv_getenv("PERL_MEM_LOG"));

        HV *env_hv = get_hv("ENV", 0);
        if (!env_hv)
           croak("wut");

        SV **svp = hv_fetchs(env_hv, "PERL_MEM_LOG", 1);
        sv_setpvs_mg(*svp, "s");

        printf("C2: getenv : %s\n", getenv("PERL_MEM_LOG"));
        printf("C2: PerlEnv_getenv : %s\n", PerlEnv_getenv("PERL_MEM_LOG"));
    }

__EOS__

sub get_env { $ENV{PERL_MEM_LOG} // "[undef]" }

{
    say "Before: ", get_env();
    set_env_test();
    say "After: ", get_env();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM