Perl Inline C code inside nginx Perl module

Ondrej Jombik jombik at platon.org
Sun Apr 15 17:01:42 UTC 2018


On Fri, 13 Apr 2018, Maxim Dounin wrote:

>> As you can see in my example, I am not even using or calling test_fnc()
>> yet. But Perl code simply fails on startup with this error message:
>>
>> -- Unit nginx.service has begun starting up.
>> nginx[20011]: nginx: [emerg] require_pv("inlinetest.pm") failed: "Running Mkbootstrap for inlinetest_0cff
>> nginx[20011]: chmod 644 "inlinetest_0cff.bs"
>> nginx[20011]: "/usr/bin/perl" "/usr/share/perl/5.24/ExtUtils/xsubpp"  -typemap "/usr/share/perl/5.24/ExtUt
>> nginx[20011]: x86_64-linux-gnu-gcc -c  -I"/" -D_REENTRANT -D_GNU_SOURCE -DDEBIAN -fwrapv -fno-strict-alias
>> nginx[20011]: x86_64-linux-gnu-gcc: error trying to exec 'cc1': execvp: No such file or directory
>> nginx[20011]: Makefile:332: recipe for target 'inlinetest_0cff.o' failed
>
> The problem is that your PATH is empty when relevant compilation
> happens.  You try to set it in the code using "$ENV{'PATH'} =
> ...", but it doesn't work as this happens _after_ "use Inline...",
> because "use ..." operators are executed at compile time in Perl,
> much like BEGIN{}.
>
> A simple fix would be to set PATH in a BEGIN{} block at compile
> time:
>
> BEGIN { $ENV{'PATH'} = '/bin/:/usr/bin/'; }
> use Inline ...
>
> Alternativel, you can use nginx "env" directive to set PATH or
> preserve it from original environment, see http://nginx.org/r/env.

Thanks Maxim, it worked like a charm.
Your help is very appreciated!

I prefer using BEGIN { $ENV{'PATH'} = ... } construction, because this
will have scope for Perl module only, while nginx "env" directive would
be nginx-wide. Is this assumption correct?

Also here is some unrelated additional info which may be useful for
someone in the future:

If Inine C code is in Perl module and your C code is in __DATA__/__C__
section, using "Inline->init" statement is neccessary. Also trailing
"1;" is important and obviously must be placed before __DATA__.

Example:

package PACKAGENAME;

use strict;
use warnings;
use base qw(Exporter);
use Carp;
use Exporter ();
use Inline 'C' => 'DATA',
    name => 'PACKAGENAME';
Inline->init;

use vars qw(@EXPORT @EXPORT_OK %EXPORT_TAGS $VERSION);

$VERSION     = do { [ q$Revision: 30336 $ =~ /(\d+)/g ]->[0]; };
@EXPORT      = qw( example_function_for_export );
@EXPORT_OK   = qw( example_function_for_export );
%EXPORT_TAGS = qw();

1;

__DATA__
__C__

/* here goes your C code */

void example_function_for_export(int num)
{
     fprintf(stderr, "%d\n", num);
}

--
Ondrej JOMBIK
Platon Technologies s.r.o., Hlavna 3, Sala SK-92701
+421222111321 - info at platon.net - http://platon.net

Read our latest blog:
https://blog.platon.sk/icann-sknic-tld-problemy/

My current location: Bratislava, Slovakia
My current timezone: +0100 GMT (CET)
(updated automatically)



More information about the nginx mailing list