develooper Front page | perl.inline | Postings from October 2002

Death to XS...

Thread Next
From:
Brian Ingerson
Date:
October 9, 2002 13:06
Subject:
Death to XS...
Message ID:
20021009130615.A27543@ttul.org
....well maybe not yet. XS is definitely the thing that wouldn't die, but
I think I can put a couple more nails in her coffin.

I went out to breakfast here in Seattle with my laptop and played around with
Attribute::Handlers. Here's what I came up with:

    use Inline C => ATTRIB;

    print dubble(10), "\n";
    print bubble(10), "\n";
    print trubble(10), "\n";

    sub dubble :inline('int dubble(int n)') {q{
	return x * 2; /* yes, this is C code */
    }}

    use Inline C => q{
    int bubble(int n) {
	return x * 2;
    }
    };

    sub trubble :inline {{
	int x = SvIV(ST(0));
	XSprePUSH;
	PUSHi((IV)(x * 2));
	XSRETURN(1);
    }}

So what's going on here? Well, first of all, all C compilation is now
happening at Perl compile time, thanks to Attribute::Handlers. This is
good. I played with A::H, and it definitely give me all the right info
at the right time to do the right thing!

The functions dubble, bubble and trubble all do the same thing. The
difference is how they are implemented at the glue (XS, etc) layer. At
this level they are quite different.

First dubble. This elegant creature has automatic typemapping provided
by the function prototype that is passed in thru the :inline()
attribute. Internally it has no wrapper though. It uses PPCODE style
glue. This means that dubble() can only be called from Perl, not from C.
Dubble would probably be slightly faster than bubble.

bubble() is the traditional Inline style. It creates a glue wrapper that
calls the real bubble. That means bubble can also be called from C.

trubble() is the most trouble to write, but it gives you almost full control.
No free typemapping to worry about. ;) trubble() would probably be as fast as
you could get.

---

You could argue that besides the slight potential speedups, this is just a
distraction. Maybe, but I just thought of one thing you can do with this
style that you can't with the old. Perl prototypes!

Suppose you want a subroutine that works with arrays:

    use Inline C => ATTRIB;

    my_push(@foo, $bar);

    sub my_push(\@$) :inline('void my_push(AV* av, SV* sv)') {q{
        ...
    }}

We can now get this behaviour for free, using the real Perl prototype
syntax. No inventing some comment embedded prototype hinting hack, like
we've discussed in the past.

---

Now to answer the question of how to do this in a module. The first
example would create 3 shared objects. That's ok. But not for a module.
I want to stick to one .so per .pm. I figured out a solution that I
think works nicely and also makes it cleaner to do the multiple
functions that Mark Fowler wanted to do.

    use Inline C => ATTRIB;  # needed to require Attribute::Handlers
    use Inline C => ALL =>
               NAME => 'Foo::Bar::Baz',
               VERSION => '1.23';

    use Inline C => <<END;
    void foo() {
        ...
    }
    END

    sub bar : inline('int bar(char* s)') {
        ...
    }

    __END__
    __C__
    int baz() {
        ...
    }

The ALL keyword in the <source> position, tells inline to collect all
subsequent Inline C invocations into one big code section. Therefore we
get one big .so.

Notice there is no 'use Inline C=>FINISH' command. How do we know when to
actually build/load? In the Inline::INIT block, of course. I had
forgotten about that before.

This seems to nicely solve all our use cases. One thing to remember is that
symbols aren't loaded (can't be used as barewords) until the end. This is the
same as with the DATA section today.

---

Just to be pedantic, the attributes stuff can be used with other
languages and/or config parameters.
  
    use Inline Guile => ATTRIB;

    sub blah :inline {
        <<END, HAVE_FUN => 1;
    ... (guile code)
    END
    }

    # or

    sub ugh :inline {q{
    ... (guile code)
    }, HAVE_FUN => 1 }

I'm not sure of the API to other languages yet, just wanted to show how
it would work from the user perspective.

Cheers, Brian

PS All of this stuff is open to discussion and definitely is NOT slated
   for Inline-0.44. 0.44 is meant to be a polished 0.43. 0.45 is when
   all hell will break loose! ;D

PS If somebody knows how to do this stuff in 5.6.0 using just
   attributes.pm, please speak up. attributes.pod makes my head hurt.


Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About