Today I was experimenting with wrapping some OpenGL calls (yes, I know
I shouldn't be doing this from scratch -- but from what my coworker
tells me, OpenGL.pm is a non-starter, and I haven't gotten around to
looking at SDL::OpenGL). I quickly ran into the annoyance of having a
lot of constants that I needed to wrap, and it seemed like the only
way to do it was to stick in a big messy
my $pkg = __PACKAGE__;
use Inline ... BOOT => <<"END";
HV* stash = gv_stashpv($pkg, 0);
SV* val_GL_LINES = newSViv(GL_LINES);
newCONSTSUB(stash, "GL_LINES", val_GL_LINES);
SV* val_GL_ONE_MINUS_ALPHA = newSViv(GL_ONE_MINUS_ALPHA);
newCONSTSUB(stash, "GL_ONE_MINUS_ALPHA", val_GL_ONE_MINUS_ALPHA);
.
.
.
END
(this is partly from memory; forgive the details). This works ok, but
is very laborious. I decided the way I'd prefer to do this is to
insert special comments into my code like:
// const iv GL_LINES
// const iv GL_ONE_MINUS_ALPHA
// etc.
and have things automatically wrapped. (Ok, not the greatest
interface. I think I may switch to scanning the actual .h file or more
likely using gcc -dM on the header file to get everything in one
shot.)
I managed to do this, but only through some exceedingly grotesque
hacks. I created a filter subroutine (as in, the sort of thing
configured into Inline with FILTERS => [ \&grab_constants ], only not
(see below)) that scans through my source code and grabs out the
comments and constructs a big BOOT section containing them, then
sticks that into the Inline object's {ILSM}{XS} something or other.
The main problem I encountered is that if you give FILTERS a simple
CODE ref, it only passes in the source code -- there is no way to get
access to the $o Inline object. I was able to hack around this by
using the Inline::Filters support (which I don't have installed) by
faking $INC{'Inline/Filters.pm'} and Inline::Filters::new and I don't
remember what else, because for some reason those routines are
privileged and are passed the $o object. (I'm using this horrible
mechanism for production code, too! But it's not that bad, since as
you may infer from my previous message I don't ship with anything but
the Inline-generated .so and .pm files. So it's only the development
path that is messy.)
So I would request that there be some way of getting that object, and
perhaps an interface for cleanly adding things to it (eg the BOOT
section) without mucking with its hash contents directly. For the
first, it would be enough if $o were simply passed as the second
argument to filter CODE refs -- which unfortunately would be a bit
ugly, because that would be the opposite order of arguments as
Inline::Filters-style filters are given those two values.
As usual, I could dig up the actual code if people want to see it. I
noticed a few requests for something like this, so we'll see if any of
those people manage to slog to the end of this message.
Is there an easier way of doing something like this?
Ah, wait, I can think of one: use the same source filter, but instead
of generating a BOOT section, generate a new init_constants() C
function and append it to the input file as the result of filtering.
Then the BOOT section can always just call that function. Hmm, why
didn't I think of that earlier...? Still, I think user-defined CODE
ref hooks should be allowed to play with the Inline state object. It's
just too generally useful.