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

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

I used to set timeout on socket with the following code:

my $timeout = pack( 'L!L!', $seconds, 0 ); defined $socket->sockopt( SO_RCVTIMEO, $timeout ) or die "Couldn't set timeout: $!";

And it worked just fine till they released NetBSD 6.0. It uses 64-bit time_t on all architectures, so I'm getting failures from cpan testers for NetBSD 6.0 on i386. Now I'm looking for a new elegant way to pack timeval. I can easily do it in C:

use 5.010; use strict; use warnings; use Inline C => 'DATA'; my $timeval = pack_timeval(2,0); __DATA__ __C__ SV* pack_timeval(time_t tv_sec, long tv_usec) { struct timeval tv; tv.tv_sec = tv_sec; tv.tv_usec = tv_usec; return newSVpv((char *) &tv, sizeof(struct timeval)); }
But I don't see any way to get size of time_t using pure Perl, it seems Config doesn't provide this parameter.

Replies are listed 'Best First'.
Re: Packing struct timeval
by Anonymous Monk on Nov 24, 2012 at 11:00 UTC
    $ perl -V:timeincl -V:timetype timeincl='/usr/include/sys/time.h '; timetype='time_t';

    Then maybe Convert::Binary::C can help ... much easier to abandon pure-perl :)

      Thank you, that's definitely interesting, but not exactly suit my taste ;) I tried to make a quick example with it and failed. First, my timeincl contains two files:
      $ perl -V:timeincl timeincl='/usr/include/x86_64-linux-gnu/sys/time.h /usr/include/time.h + ';
      Second, it seems not that easy to make it parse time.h, you may have to add some include directories and define some macros, depending on the system, so it is not that portable. I stopped with this:
      use 5.010; use strict; use warnings; use Convert::Binary::C; use Config; my $c = Convert::Binary::C->new; $c->Include( '/usr/include', '/usr/include/x86_64-linux-gnu/sys/', '/usr/include/x86_64-linux-gnu/' )->Define('__WORDSIZE=64'); $c->parse_file('/usr/include/x86_64-linux-gnu/sys/time.h'); my $timeval = $c->pack( 'struct timeval', { tv_sec => 1, tv_usec => 0 +} );
      And it gave me
      bits/wordsize.h, line 7: macro '__WORDSIZE' redefined unidentically included from /usr/include/x86_64-linux-gnu//sys/cdefs.h:378 included from /usr/include/features.h:357 included from /usr/include/x86_64-linux-gnu/sys/time.h:23 at pack_ +timeval2.pl line 10.
      I probably would be able to make it work on my particular system, but not in general case. And it requires that includes were installed on a target system, which may not be the case.

        I tried to make a quick example with it and failed.

        I kinda knew it would -- reinventing a compiler is hard -- it much simpler to compile a c program to dump the structure of struct, kinda sorta the trick C::DynaLib::Struct/hparse employs

        I suppose you could always "fingerprint an os" and build a database of time formats ... pure-perl is pure insanity if you ask me, much less work to install a compiler :)