in reply to Passing a structure from C to Perl

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..

Replies are listed 'Best First'.
Re^2: Passing a structure from C to Perl
by bliako (Abbot) on Mar 23, 2018 at 01:27 UTC

    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

        With a single-parameter JSON string you can pass a very complex parameters structure which can be parsed programmatically at the perl side (of course you may need to intervene to extend your perl-side parser if you change structure of params string and for params checking).

        If you use JSON you can pass very complex data structures including arrays, arrays of arrays, hashes, arrays of hashes, etc. the sky is the limit.

        You asked: "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."

        Which is exactly what I am saying (borrowing Corion's JSON idea). In the simplest scenario, you can pass a JSON array of arbitrary length for your parameters which is equivalent to running your perl script with an arbitrary length of arguments.

        But when you want to add more structure to your parameters (e.g. the hashes above) then it will be a bit painful to do that via the script arguments.

        And lest not forget about parameter checking at perl side (will be needed if from time to time a human runs the script too). If you want to do that, you have to modify the logic each time your parameters spec changes (well not necessarily but usually). Now with JSON (string or file) I can see a way where you also pass the logic for checking your parameters, as a perl sub for example. Eval is very dangerous (and in many security scenarios forbidden - e.g. if that is part of a web/CGI then forget it) but I am enumerating some possibilities without knowing much about your program's environment ...

        Jockingly: I can see someone creating the whole perl script from within C, from scratch or from a template, where the logic of parameter checking (perl side) is programmatically created and inserted from within the C program into the perl program, every time you change params specs in the C program.

        Suddenly all the logic moves to the C program.

        Or, from within C, insert(=hardcode) all the parameter values where they are supposed to go in the perl script on the fly, from a template. In this way a perl script for one-time usage is created with all initial state (params) hardcoded in it. And all params-checking is done exclusively in C. Very clean indeed. Good for running as a pipeline in a parallel environment. And you can re-run the program for debugging the pipeline without being concerned about parameter strings or files.

        Again, if you give more details I can be more specific.

        regards, bliako

        Regarding your question about extracting fields from the XML string. I don't know.

        There are perl modules for sure such as XML::Parser.

        But for JSON it is that simple from cpan's JSON page and this http://www.perlmonks.org/?node_id=1138138 for utf8-related problems:

        use warnings; use utf8; binmode STDOUT, ":utf8"; use JSON; use MIME::Base64; use Data::Dumper; die("exactly 1 param is needed.") unless scalar(@ARGV) == 1; my $params_str_base64 = $ARGV[0]; my $json_str = MIME::Base64::decode_base64($params_str_base64); my $params_as_perl = JSON::from_json($json_str); print Dumper($params_as_perl);
Re^2: Passing a structure from C to Perl
by Anonymous Monk on Mar 22, 2018 at 12:13 UTC
    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.