Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

Re: Follow the Interface? (XS)

by tye (Cardinal)
on Jul 24, 2003 at 14:03 UTC ( #277543=note: print w/ replies, xml ) Need Help??


in reply to Follow the Interface?

I've been repeatedly frustrated by Perl interfaces to external libraries where someone tried to design some new "Perl-like" interface to the library, wrote a ton of XS code, and too often produced what I'd frankly categorize as, well, "<insert curse word>". (:

They usually produce something that solves the specific problem that they have in mind but that doesn't support lots of other potential uses for the library. They also write way too much XS code and so end up with awkward interface quirks and several outright bugs.

I strongly feel that the best approach is to write the XS code to be *very* C-centric. Using Inline::C over traditional XS can help you do this. I find that a very thin layer that expects data to be provided already in a C-friendly format and returning it in a C-friendly format is less likely to contain bugs and more likely to give the advanced user the full power of the library.

Such also (contrary to the suggestions of the XS manuals) allows more efficiency by letting you make multiple calls into the library without doing any converting of data (and allows you to combine parts of the library in powerful ways).

This should be your first step. Simply wrap the library very thinly so that you can get at the full power of it from Perl (though probably not very easily).

If you have complex C data structures, then your second step is to write C or Perl code to combine/extract data to/from your data structures. IMO, there often aren't any great ways to do this. I'd probably end up using pack/unpack in routines written in Perl if possible (that is, if I could write portable code that way). My second choice would be XS routines that take one argument that is a Perl string to contain/containing the complex structure and a bunch of scalars to contain/containing the parts (because this way XS can do all of the conversion for you and your C code simply needs to combine or extract).

You should avoid trying to manipulate (or even access) Perl aggregates (arrays/hashes/objects) from C code or doing any manipulation of the call stack (let Inline::C do that part and only use simple parameters). Such code won't handle magic nor tie and probably won't get autovification right. And it is very likely to contain bugs.

Your third step is to write Perl wrapper subroutines that accept data in Perl-friendly format, convert it to C-friendly format if needed, call the library, convert the C-friendly format to Perl-friendly format, if needed. If the C-friendly data structures aren't very complicated, then you can skip the second step above and just do the conversion directly in these Perl wrappers.

Your fourth step is to write a Perl-friendly interface (that is much easier to use but might not provide the full power of the interface). It is nice to make the 'easy' interface useful even when one is bypassing parts of it to get to advanced functionality, but this can be a difficult design problem.

Two examples of this philosophy are Win32::TieRegistry and Win32API::File.

TieRegistry is 100% Perl and uses Win32API::Registry to get at the C calls. You have the full power of the registry calls via Win32API::Registry (even to the point of supporting the arguments to functions that are reserved for future use and should be NULL or 0 with current versions of the library and providing calls that you usually don't need or even that require complex data structures that dealing with are outside the scope of this module).

Win32::TieRegistry provides a very Perl-like interface (IMHO). It has a lot of DWIM features and places a lot of importance on the convenience of the module user. This interface would have been impossible to come close to writing XS code.

Win32API::File provides full-power access to several file-related API calls. There are surely several that should still be added, but the ones that are there can be used in every way that they can be used in C (except that there might be a few ways that you could produce a 'core dump' in C that I don't support in the Perl interface). On top of this, there are several Perl-friendly wrappers.

Read the module documentation and compare CreateFile() vs. createFile(). CreateFile() is the full-power, raw (and rather ugly) access to the underlying C API. createFile() is the Perl version that provides intelligent defaults, named arguments, and much simpler ways to specify things like access permissions and sharing levels.

                - tye


Comment on Re: Follow the Interface? (XS)
Re: Re: Follow the Interface? (XS)
by liz (Monsignor) on Jul 24, 2003 at 14:29 UTC
    ...I strongly feel that the best approach is to write the XS code to be *very* C-centric...

    This sounds like a tool that would take an API description of an external library and generates the perl modules source for the thin layer from that. Does such a beast exist already (not thinking about h2xs, as that is only fetching constants, right?)

    Update:So you mean you should use SWIG to get the thin Perl layer and work from there?

    Liz

      I've never used SWIG. But that sounds like a worthwhile suggestion that would often work well.

                      - tye
Re2: Follow the Interface? (XS)
by dragonchild (Archbishop) on Jul 24, 2003 at 14:46 UTC
    Although I have not read the code, I find that PDFLib has an extremely good and easy-to-use API to an underlying C library. The rather amazing thing is that they support something like 7 languages over this library. It is proprietary, but still pretty cool.

    ------
    We are the carpenters and bricklayers of the Information Age.

    Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement.

    Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://277543]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others studying the Monastery: (10)
As of 2014-10-01 13:01 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    What is your favourite meta-syntactic variable name?














    Results (18 votes), past polls