Almost two years ago I realized that Perl 5 has calling conventions just as Parrot does.
That is, just as every Parrot function that passes two integers and a PMC to function and receives a string back looks the same in terms of the registers used, every Perl 5 function that passes two integers and a blessed scalar looks the same in terms of what's on the stack and where.
The same goes for C.
Any Perl function that passes arguments to a C function passes them the same way. The thunking layer that pulls arguments off of Perl's stack and passes them to the C function is the same for all Perl and C functions with the same signatures. The only difference is the C function to call.
Why write all that code more than once? Why compile all that code more than once? Why make people who may not even have compilers installed compile that code when you could have done it when you built Perl and now they never need to have a compiler installed to use pre-compiled C libraries?
One answer (not a good answer, but an answer) is "Because it's difficult to do."
Difficult is not impossible.
I just released P5NCI to the CPAN today. (That link won't work for a couple of hours after I posted it.) I've mentioned it before. I even added a hack about it to Perl Hacks (so I knew I needed to make it work sufficiently to release soon.)
It's not perfect and it's not complete, but it works. I know -- I spent a couple of hours last night and a couple of hours this afternoon wondering at platform-specific differences until I realized that higher-order C isn't entirely portable.
Yet now it works.
Now I need TPF Summer of Code 2006 student to make it perfect. Do you know anyone?
I had wondered why ActiveState could do this with DCOM DLLs in Win32::OLE but we needed at least Inline or and sometimes XS explicit wrappers on the *nix side.
Thank you!
In P5NCI.pm, for
do you perhaps meanmy $library = P5NCI::find_lib( 'nci_test' );
my $library_path = P5NCI::load_lib( $library_path );
my $library_path = P5NCI::find_lib( 'nci_test' );
my $library = P5NCI::load_lib( $library_path );
The POD doesn't say that 'v' is invalid as a input argument type, but that would be the inference, since it's void not void*.
A lot of C, C++ APIs would be feasible with this system if an opaque void*
object handle was a permitted signature element. But how to safely hold one untamperably on the Perl side would be an issue -- we don't want to go probing through the heap or worse by passing random ints as void*'s. re-introducing pointers by a back door would be a bad thing, but all but the simplest C APIs and all C++ APIs have object cookies to return. I suppose the implementation could refuse any input void* value it hasn't seen before as an return void* parameter, and and maybe the magic values 0 and -1 = ~0x0 ? Of coures, there are performance implications
Thanks again,
Re:P5NCI - neat idea, POD typo, extensions?
chromatic on 2006-05-09T07:59:10
You're right about the two documenation issues. The first is a typo and the second is true --
v
is only valid as the output parameter type.Adding support for read-only pointers (
void *
) is easy. Enforcing it isn't difficult either; Perl SVs can contain plain integers and I think I can toggle the read-only flag on them. I hesitated to add those until I could make writing to struct pointers easy, but as long as people know that that's the trickiest part and it's possible, I can release this in bits and pieces.I've just uploaded version 0.20 with everything but read-onlyness. (I threw in functions with no arguments as a bonus). I might have to ditch XS and write the C code directly to make that work.