Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

Inline::C and environment vars

by gri6507 (Deacon)
on Nov 11, 2011 at 17:13 UTC ( [id://937627]=perlquestion: print w/replies, xml ) Need Help??

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

I have a Perl script similar to
my $relSourcePath; my $inlineCFile; my $inlineBuildDir; my $libDir; my $incDir; BEGIN { # this file is in the same directory as the rest of the sources $relSourcePath = File::Spec->rel2abs(dirname($0)); die "Install path must not have spaces.\n" if $relSourcePath =~ /\ +s/; # Need to build the path to the Inline C file here, so that we cou +ld # reference it below my @dirs = (); push @dirs, $relSourcePath; $inlineCFile = File::Spec->catfile(@dirs, "my_wrapper.c"); push @dirs, ".Inline"; $inlineBuildDir = File::Spec->catdir(@dirs); pop @dirs; push @dirs, "lib"; $libDir = File::Spec->catdir(@dirs); pop @dirs; push @dirs, "include"; $incDir = File::Spec->catdir(@dirs); } use Inline ( C => Config => LIBS => "-L$libDir -lmylib", INC => "-I$incDir", DIRECTORY => $inlineBuildDir, ); # this is the C source file for interfacing to the library. Yes, this +could be # done natively in Perl, but this is just as easy (and probably faster + to # execute). use Inline C => "$inlineCFile"; $ENV{MYVAR} = "my_var_value"; print "ENV{MYVAR} = '" . qqq("MYVAR") . "'\n";
The my_wrapper.c file is basically a wrapper to glue together mylib with Perl code. As a test, I added a function qqq to my_wrapper.c as follows:
char * qqq(const char *envName) { return getenv(envName); }
When I run the Perl script, I see that Perl does indeed set the environment variable so that the qqq() function can extract its value. However, it appears that the value of the environment variable is not the same when executing code within mylib. It's as though, mylib was loaded into a different memory space

Is there anything I can do in Perl to set the environment variable so that it's visible to mylib?

P.S. As a sanity test, I set the environment variable on the command line first and then ran my test. The value used by mylib is the one that was set on the command line and not the one from within Perl.

Replies are listed 'Best First'.
Re: Inline::C and environment vars
by BrowserUk (Patriarch) on Nov 12, 2011 at 01:25 UTC

    Perl does not use the C runtime's copy of the environment. Probably for very good reasons.

    Rather than accessing the CRTs copy from XS, you should access Perl's copy instead.

    This prints the value of the pre-existing envvar 'path', then nothing from the (probably) non-exitant envvar 'fred', before setting 'fred' from Perl and then retrieving it from XS.:

    #! perl -slw use strict; use Inline C => Config => BUILD_NOISY => 1; use Inline C => <<'END_C', NAME => 'XSenv', CLEAN_AFTER_BUILD => 0; char *test( char *name ) { HV *env = get_hv( "ENV", 0 ); SV **pval = hv_fetch( env, name, strlen( name ), 0 ); if( pval ) { SV *val = *pval; return( SvPVX( val ) ); } return( "" ); } END_C print test( 'path' ); print test( 'fred' ); $ENV{fred} = 12345; print test( 'fred' );

    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      This is a good suggestion, but unfortunately, does not address my problem. The issue that I have is that mylib will have different behavior depending on value of environment variables, and I do not have full control over that library to change it to use arguments instead of env vars. This solution would have been ideal in cases where there is full control of the library sources.
Re: Inline::C and environment vars
by syphilis (Archbishop) on Nov 12, 2011 at 00:04 UTC
    I set the environment variable on the command line first and then ran my test. The value used by mylib is the one that was set on the command line and not the one from within Perl

    Yes, I see the same behaviour (on Win32, btw).
    I even tried setting the environment variable at the very beginning of the perl script, inside a BEGIN{} block ... but the external library still doesn't see that value.

    I'm wondering whether a dynamic (shared) library might see the new value, but I don't think it would. (You could try that if you think it's worth a shot - my 'libmylib' was a static library.)

    Only other thing I can think of is that your library needs a 'setenv' implementation, which you can then call from perl via an Inline::C wrapper whenever you alter an environment variable.

    Cheers,
    Rob
Re: Inline::C and environment vars
by Anonymous Monk on Nov 12, 2011 at 07:24 UTC

    Env::C - Get/Set/Unset Environment Variables on the C level

      Thanks! This is exactly what I was looking for.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://937627]
Approved by Corion
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others perusing the Monastery: (4)
As of 2024-03-29 07:57 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found