http://qs1969.pair.com?node_id=479645

esskar has asked for the wisdom of the Perl Monks concerning the following question:

Hi, it's me again! :)
You may know that I embedded perl.
I keep several persistent interpreters in different threads.
Do you know a way to set %ENV and the workingdirectory and redirect STDIN without writing external Perlcode but calling the PerlAPI from my C/C++ program?
Thanks for help!
  • Comment on Perl Embedded: Setting %ENV, STDIN and Workingdirectory

Replies are listed 'Best First'.
Re: Perl Embedded: Setting %ENV, STDIN and Workingdirectory
by tlm (Prior) on Jul 30, 2005 at 23:09 UTC

    I'm sure there are more enlightened ways to do this, but my ignorant (and 100% untested) approach would be to use eval_pv to evaluate a string of Perl code within my C program.

    As far as changing the working directory, at least in Unix, I'd just use chdir(2); no need to get perl involved for this.

    the lowliest monk

      well, since i have multiple threads, i think using the windows equivalent to chdir would affect all threads. But thats not a good idea, because one script has to run in a different directory than a other.
      But thanks for the eval_pv hint; i will be testing it!
Re: Perl Embedded: Setting %ENV, STDIN and Workingdirectory
by esskar (Deacon) on Jul 31, 2005 at 23:28 UTC
    Okay; setting %ENV is rather simple.
    To make it simple, i wrapped part of perls variable types and their functionality in a C++ Class. then i wrote a function as part of my interpreter class that returns a hash object
    Hash Interpreter::GetHash(const char *name, bool create /*=false*/) { Hash hash; hash.Attach(get_hv(name, create)); return hash; }
    And now i'm able to do the follwing fun stuff:
    Perl::Hash perlenv = m_perl->GetHash("ENV"); if(perlenv.ValidPtr()) { perlenv.Store("foo", Perl::Scalar("bar")); perlenv.Store("bar", Perl::Scalar("foo")); }
    Fun, isn't it? :)
Re: Perl Embedded: Setting %ENV, STDIN and Workingdirectory
by esskar (Deacon) on Aug 02, 2005 at 20:56 UTC
    well; i haven't seen it.
    it's actually that simple
    Scalar Interpreter::Eval(const char *code, bool croak) { Scalar retval; retval.Attach(eval_pv(code, croak)); return retval; } void PerlObj::RedirectStdout(const std::string & filename) { std::string code = ""; code += "open(YAPPPSSTDOUTSAVE, \">&STDOUT\");"; code += "open(YAPPPSSTDOUTFILE, \">"; code += MakeUnixFilename(filename); code += "\") or die \"Unable to override STDOUT!\";"; code += "open(STDOUT, \">&YAPPPSSTDOUTFILE\") or \ die \"Unable to override STDOUT!\";"; m_perl->Eval(code.c_str(), true); m_redirectstdout = true; } void PerlObj::RedirectStdin(const std::string & filename) { std::string code = ""; code += "open(YAPPPSSTDINSAVE, \"<&STDIN\");"; code += "open(YAPPPSSTDINFILE, \"<"; code += MakeUnixFilename(filename); code += "\") or die \"Unable to override STDIN!\";"; code += "open(STDIN, \"<&YAPPPSSTDOUTFILE\") or \ die \"Unable to override STDIN!\";"; m_perl->Eval(code.c_str(), true); m_redirectstdin = true; } void PerlObj::ResetStdio() { std::string code = ""; if(m_redirectstdin) { code += "open(STDIN, \"<&YAPPPSSTDINSAVE\");"; code += "close(YAPPPSSTDINFILE);"; m_redirectstdin = false; } if(m_redirectstdout) { code += "open(STDOUT, \">&YAPPPSSTDOUTSAVE\");"; code += "close(YAPPPSSTDOUTFILE);\n"; m_redirectstdout = false; } if(code != "") m_perl->Eval(code.c_str(), true); }
    and no i can just call "chdir" to set the workingdirectory because it will just set the wd of the current interpreter.
    It's fun! :) i'm happy!