Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked

catch "use Inline::C" death

by bliako (Abbot)
on Jun 14, 2024 at 09:36 UTC ( [id://11159977]=perlquestion: print w/replies, xml ) Need Help??

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

I have a test which must fail as it tests passing bogus CFLAGS to Inline::C. e.g.

use Inline C => Config => ccflagsex => '-test-bliako-A', ; ... use Inline C => <<'EOC'; #include <stdio.h> ... EOC

The problem is that passing bogus CFLAGS to use Inline C => Config ... dies and my test fails without getting the chance to recognise that actually the test was passed as the die was expected.

I tried to enclose said codeblock in eval { }; but I see no difference. Test fails.

I find Inline::C using the use Inline C ... impractical and unecessary (perhaps it comes from Inline). So, is there a way to separate use Inline C; from its Config and Code sections? Ideally:

use Inline C; Inline::C::config(...); Inline::C::embed_C_code(... c code ...);

Alternatively, how can I catch the croak's and die's from when use'ing a module with Test::More.

Or perhaps using require ... ?

ps. I also tried to enclose it in a try{}catch{}; with same result: death

bw, bliako

Replies are listed 'Best First'.
Re: catch "use Inline::C" death
by Corion (Patriarch) on Jun 14, 2024 at 10:41 UTC

    use is basically require + ->import, so you can do the following:

    eval { require Inline; Inline->import( C => Config => ccflagsex => '-test-bliako-A' ); Inline->import( C => $c_code ); };

      Thanks Corion++ that does the trick! nice.

      I found another way with The-bind()-Function of Inline which works fine for multiple code blocks and recovers from previous bad configuration. Unfortunately there is a caveat mentioned in the documentation, which I did not understand:

      Although bind() is a powerful feature, it is not recommended for use i +n Inline based modules. In fact, it won't work at all for installable + modules.

      This is how I use bind() with code and configuration:

      use Inline; Inline->bind( CUDA => $code, BUILD_NOISY => 1, clean_after_build => 0, warnings => 10, );

      And it is happy inside eval or try/catch (Try::Tiny).

      I was thinking about this and realised that one can have multiple Inline code blocks. I have tried it and also within eval and try/catch and they work except that if a configuration fails (for my tests) then it sticks with it and does not seem to re-configure. Using bind() as above seems to recover from previous bad compilations.

      Inline's preferred way is to specify the code in a BEGIN block and then use Inline => ... which does not allow for inlining code dynamically. bind() does.

      PS: I have also asked the author a question here

        The advantage of "use Inline C => ..." is that it happens at compile-time when there is still a chance to declare functions for use further down in the module. Otherwise, perl code later in the module (as it is being compiled) won't know that the XS functions exist, forcing you to use parentheses when calling them.

        This advantage might not apply to that many people, but I'm guessing that was why it was done as a BEGIN behavior.

Re: catch "use Inline::C" death
by hippo (Archbishop) on Jun 14, 2024 at 10:29 UTC

    If I've understood what you are attempting correctly then it works if you split out the Inline parts into a separate file and do it like this:

    $ cat use strict; use warnings; use Inline C => Config => ccflagsex => '-test-bliako-A', ; use Inline C => <<'EOC'; #include <stdio.h> EOC $ cat bliako.t use strict; use warnings; use Test::More tests => 1; do './'; isnt $@, '', 'Inline C fails as expected'; $ prove -v bliako.t bliako.t .. 1..1 ok 1 - Inline C fails as expected ok All tests successful. Files=1, Tests=1, 1 wallclock secs ( 0.03 usr 0.01 sys + 0.82 cusr + 0.19 csys = 1.05 CPU) Result: PASS $



      thanks but ouch! i was afraid of this.

Re: catch "use Inline::C" death
by syphilis (Archbishop) on Jun 14, 2024 at 10:18 UTC
    Here's how I see what you are, in effect, seeking:
    You have a perl extension (ie a module that contains XS code).
    You want the "perl Makefile.PL" step to pass.
    But you want the "make" step to fail.
    Then you want the "make test" script to report the failure - even though "make test" cannot possibly be run if "make" failed.

    It seems to me that you are asking for the impossible.


Log In?

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

How do I use this?Last hourOther CB clients
Other Users?
Others browsing the Monastery: (6)
As of 2024-07-17 09:13 GMT
Find Nodes?
    Voting Booth?

    No recent polls found

    erzuuli‥ 🛈The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.