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

Hi,

I have a C program (let's call it A) which calls a perl5 script (B) and it passes some parameters to it. The scope of the script is now changing and I need to pass more parameters to it. And in the future, even more. Instead of passing individual parameters to the script, I would like to pass a structure with all these parameters and keep extending the structure as and when I need to pass more parameters. This will keep the interface between the C code and Perl script constant (with just one parameter, the structure) and also keeps the code clean. How can I do this...? I have been searching the documentation, but unable to find the solution.

Thanks, Praveen

Replies are listed 'Best First'.
Re: Passing a structure from C to Perl
by Corion (Patriarch) on Mar 22, 2018 at 11:53 UTC

    Consider writing all the data to a file and then reading it from that file with Perl. That way you would only pass around the name of the file with the structure in it.

    Common structures are JSON files, or .ini files (or other configuration files), but depending on your actual structures, maybe XML is easier to read and write for all programs involved..

      Corion's advice is fine but in the case of running the C program many times in parallel, or the perl script is called in a fork many times, you will need to construct the parameter files' names such that they don't overwrite each other. That will probably involve the PID of the C program/children.

      If this is the case, I would keep the suggestion of formatting the perl script's parameters as a single JSON or XML string but avoid writing it to a file. Instead, pass that string to the perl program as a command line parameter:

      perlscript.pl '{"a":"1","b":"2"}'

      Instead of what you now have:

      perlscript.pl -a 1 -b 2

      The perl script will then decode the parameters string (whereas in Corion's advice the perl script will read the parameters file and decode its contents).

      The maximum length of a command line will be limited depending on OS.

      You have to be careful with quotes.

      If quotes or special characters are a problem, a quick hack would be to encode your parameter string using base64 and pass that to perl script which it will have to decode it and parse it. It will require more processing time though:

      perlscript.pl 'eyJhIjoiMSIsImIiLCIyIn0='
        Apologize if this is a newbie question, but in the above suggestion, what is the difference between passing the parameters as an XML string versus individual parameters? Is there a Perl utility that can be used to extract the different fields in the XML string? Regards, Praveen
      And on both the "C" and the Perl side use well-tested existing libraries to do the encoding and decoding for you. Of course it is a little more involved on the C side but there do exist utilities that can munch a struct definition or a header-file and "compile" it into a subroutine that will quickly encode or decode that structure.

        Corion suggested at least three possible data file formats. You suggest existing libraries for C. Perhaps you could elaborate on the pros and cons of some libraries on both the Perl and C sides for the given formats to help the OP make the best choice.

Re: Passing a structure from C to Perl
by BrowserUk (Patriarch) on Mar 23, 2018 at 08:11 UTC

    Personally, I'd use popen() to start the process and have the perl process read the parameters from its standard input.

    That way, you bypass all the problems of command lines -- limited lengths, quoting, dangers of binary data triggering unintended actions -- and you can pass th edata in whatever form makes most sense to you, text or binary, and write it in one big chunk or as many small chunks as you like.

    All together more satisfactory IMO.


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    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". The enemy of (IT) success is complexity.
    In the absence of evidence, opinion is indistinguishable from prejudice. Suck that fhit
Re: Passing a structure from C to Perl
by Tux (Canon) on Mar 23, 2018 at 14:55 UTC

    I really enjoy separating two processes and have then communicate, over files or through pipes or databases, but it still has drawbacks.

    I am the first to admit that solving this issue in XS might be overkill (but it would be my choice)

    Is using Inline::C an option to consider? or FFI::Library, or P5NCI?


    Enjoy, Have FUN! H.Merijn
Re: Passing a structure from C to Perl
by bliako (Abbot) on Mar 23, 2018 at 13:17 UTC

    An idea, building on the JSON params string: from within C serialise a perl object which will contain all params you want and get() methods to obtain the params. Then either write that to file and have perl read it and de-serialise/resurrect it or hardcode it into the perl script if you create the script on-the-fly as in my previous comment.

    JSON is a way to encode a data structure. Whereas the serialised perl object above goes a lot further with error-checking logic, functions, debugging messages etc. BUT it also introduces a lot of security risks; the usual eval() concerns.

    Relevant Kraftwerk lyrics:

    • Wir fahr'n fahr'n fahr'n auf der AutoInfobahn
    • I'm the operator with my pocket calculator
    • By pressing down a special key, it plays a little melody

    bliako
Re: Passing a structure from C to Perl
by pwagyi (Monk) on Mar 23, 2018 at 01:19 UTC

    I am not exactly expert on swig/XS, but can't you pass C struct as hash to perl? So if there's a new field in struct, you only have to change type map?

Re: Passing a structure from C to Perl
by rizzo (Curate) on Mar 23, 2018 at 14:48 UTC
    I have been searching the documentation, but unable to find the solution.

    Did you read about 'interprocess communication'?