> > I'm interested in dragging a C library (actually, a large
> > program with the main() omitted) lock, stock and barrel into
> > perl so I can tinker with the internals, and replace the
> > program's awful GUI quickly via Tk or somesuch.
> 
> This is possible with Inline. Check out Inline::C and Inline::C-Cookbook
> for more information, give it a try with a few simple examples, and feel
> free to email the list with your results along the way.

I just did this, and it was incredibly easy. The steps I took were:

1. Made the library compile into a shared object libengine.so.
2. Made an Engine::Inline module: (slightly modified from the original)

package Engine::Inline;
use Cwd qw(abs_path);
use File::Basename;
sub Inline {
    my $language = shift;
    if ($language ne 'C') {
        warn __PACKAGE__." does not provide Inline hints for ".
          "the `$language' language, only for C";
        return;
    }

    my $thisdir = dirname($INC{'Engine/Inline.pm'});
    my $libdir = abs_path("$thisdir/../../lib"); # directory of
libengine.so
    my $incdir = abs_path("$thisdir/../../include");
    return { LIBS => "-L$libdir -lengine",
             INC => "-I$incdir" };
}
1;

3. For each component of the C library, I made an
Engine::Inline::Component module. For example:

package Engine::Inline::PFile;
use Engine::Inline;
use Inline with => 'Engine::Inline';
use Inline (C => 'DATA',
            PREFIX => 'INLINE_');
1;
__DATA__
__C__
void* INLINE_pfopen(char* pattern, char* mode, size_t partition_size)
{
    return pfopen(pattern, mode, partition_size);
}

4. Sample code:

use Engine::Inline::PFile;
my $pfile = Engine::Inline::PFile::pfopen("/tmp/fwoing", "w", (1<<20));

(actually, I also export pfopen and the other functions, so I really do
my $pfile = pfopen(...)
but I didn't want to confuse things.)

Major caveat: even though Engine::Inline sets up the -I include path, I
can't actually make use of it by including my own header files, because
I have lots of conflicts with the perl headers. I briefly tried playing
with #define EMBED, NO_EMBED, PERL_POLLUTE, etc., but didn't really get
anywhere. So for now I just cut & paste the needed structs and typedefs
into the individual packages, and use void* all over the place to
minimize the number that I need. But this only took a few hours so far,
so I haven't really tried many things.

It's incredible how little time my first foray into Inline world took,
as compared to my first emotionally scarring venture into the XS hell,
or even the relatively gentle SWIG jungle. Thank you, Brian!

Reply via email to