http://www.perlmonks.org?node_id=877598

unlinker has asked for the wisdom of the Perl Monks concerning the following question:

I have to write a perl module that will call functions in a C-library from my perl code and I wanted to understand if the following is possible:
  1. Can I pass a reference to a string and have the C-library fill it for me so that I can de-reference it on return and get the string?
  2. Can I construct and pass a pointer to a C-struct from my perl module and have it return the struct with values filled in?
  3. Can I pass a pointer to a function and have the C library call it
While I have been a long time perl user, I have never written perl module wrappers around functions in a C-library and any pointers, suggestions and advice would be sincerely appreciated. Thank you
  • Comment on Extending with C functions - some basic questions

Replies are listed 'Best First'.
Re: Extending with C functions - some basic questions
by Anonyrnous Monk (Hermit) on Dec 17, 2010 at 08:59 UTC

    One thing to understand is that Perl references and C pointers are two different things (despite the conceptual similarities).  So,

    1. Can I pass a reference to a string and have the C-library fill it for me so that I can de-reference it on return and get the string?

    The more natural way would to be to create a new scalar value (SV) and place the C string into it, for example using newSVpv(). Then return that SV to the Perl side, where you can access it as a normal Perl string. See perlapi, perlguts and PerlGuts Illustrated.

    2. Can I construct and pass a pointer to a C-struct from my perl module and have it return the struct with values filled in?

    Perl doesn't have structs in the sense C has. So you have to convert the contents into an appropriate form, such as a hash with keys corresponding to the struct's fields.

    3. Can I pass a pointer to a function and have the C library call it

    No. See perlcall for how to do it (it comes with several examples).

    See also perlxs, perlxstut and Inline::C for the big picture of how to extend Perl with C.

      3. Can I pass a pointer to a function and have the C library call it

      No. See perlcall for how to do it (it comes with several examples).

      Well, the answer really is "Yes. See perlcall for how to do it" :)

      You can do anything with XS, but you have to provide enough "glue" so that the code provided by your C library cooperates nice with the rest of perl interfaces.

        ...depends on how you interpret the word "pointer" that the OP used.

        If you read it as "C pointer" (as I did), i.e. an address of the entry point of the function in the compiled machine code, then the answer is strictly speaking "no", because Perl alone (without the help of XS modules) doesn't provide any direct way to get at the respective address — which in turn means you can't pass it to the C function. (And even if there was a way, it would not be recommended for normal purposes. Also, Perl functions don't directly correspond to compiled machine code.)

        If, OTOH, you read "pointer" as "Perl reference", then yes, sure you can pass it to the C function and use call_sv() to call it.

        Anyhow, it doesn't really matter whether the answer starts with yes or no, as long as the OP reads the referenced manual, in which case everything will become clear (hopefully :)

Re: Extending with C functions - some basic questions
by Khen1950fx (Canon) on Dec 17, 2010 at 13:01 UTC
Re: Extending with C functions - some basic questions
by sundialsvc4 (Abbot) on Dec 17, 2010 at 14:21 UTC

    It may also be useful to contemplate pack and unpack.   “Tearing apart an in-memory structure” is what they do.   Your module would use that bit of voodoo (and yes, it is voodoo) to automagically come up with a Perl data structure containing the requisite elements, concealing all that ugliness from any and all humble supplicants.

    There’s a fair amount of this stuff in CPAN, e.g. in crufty code like DBI drivers, which you can refer to.

Re: Extending with C functions - some basic questions
by blakew (Monk) on Dec 18, 2010 at 02:26 UTC
    Can I pass a reference to a string and have the C-library fill it for me so that I can de-reference it on return and get the string?

    You don't need to take a reference first, just pass the string to your C function (think chomp). Your C function sees an SV* pointer and can directly modify the contents.

    Also, no one has suggested Inline. Let me do so, it largely prevents you from having to use XS or mess with SWIG.

      Yes, Inline is definitely more beginner-friendly that XS or SWIG and is something I plan to go with. However even for implementing integration with C libraries that require complex data structures or call-back pointers to be passed, a basic understanding of how Perl stores various data types is required. Could you point me to a beginner-friendly description of data structures used by Perl (things like SV* etc)? Thanks
        Could you point me to a beginner-friendly description of data structures used by Perl (things like SV* etc)?

        For me, the clearest description of Perl's data structures is PerlGuts Illustrated.


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.