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

Dear Monks, I have following C++ function which takes variable arguments. How can I implement it in Perl with out changing the function interface, preferably
int recordStatus(LPCTSTR sFormat, ...) { if ((m_bUseLog) &&(iLogLevel <= m_iLogLevel)) { va_list argptr; int retval; va_start(argptr, sFormat); _ASSERTE(sFormat != NULL); retval = vfprintf(m_sSourceFile, sFormat, argptr); sSourceFile.Flush(); va_end(argptr); return (retval); } }
How can i handle variable arguments in Perl?

Thanks
Kamesh

Replies are listed 'Best First'.
Re: How to implement printf like functions
by Zaxo (Archbishop) on Aug 29, 2005 at 06:44 UTC

    Perl subs nearly all handle any number of arguments, passed in as aliases in @_. Perl has printf which works just like the C function.

    sub printf_like { my ($fmt, $flag) = (shift(), 1); printf $fmt, $_ or $flag = 0 for @_; return $flag; }

    After Compline,
    Zaxo

Re: How to implement printf like functions
by sk (Curate) on Aug 29, 2005 at 06:46 UTC
    I am not sure what exactly your code does. So i am not sure how to convert it into Perl

    In Perl, the arguments to subs/functions are sent as lists. So you can put your first element as the format and the subsequent elements are the args you want to send. Here is a dummy function that does something like that

    #!/usr/bin/perl -w use strict; my @ret = pow("3 2 3 2",(2,3,5,7)); print +($_,$/) for @ret; sub pow { my ($fmt, @values) = @_; my @fmts = split /\s+/, $fmt; return map {$_**shift(@fmts) } @values; } __END__ 8 9 125 49

    The first param's first element tells you by what power the first arg should be raised.

Re: How to implement printf like functions
by fmerges (Chaplain) on Aug 29, 2005 at 08:23 UTC

    Hi,

    Could be something like this...

    sub recordStatus { if($m_bUseLog and $iLogLevel <= $m_iLogLevel) { my $format = shift; my $string = sprintf $format, @_; return length $string if(print $m_sSourceFile $string); return -1; } }

    This would be something like you have, having $m_bUseLog, $iLogLevel, $m_iLogLevel, $m_sSourceFile, as global variables. Where $m_sSourceFile is the FILEHANDLE...

    In the C++ as in the Perl, you should add some errors check, from input and also define a common error return (if return -> croack)...

    Regards,

    |fire| at irc.freenode.net

      Close, I think. However, given that we're coming from C++ to Perl, chances are that "m_" means "member variable". In other words, we're in an object method here.

      sub recordStatus { my $self = shift; if($self->{UseLog} and $iLogLevel <= $self->{LogLevel}) { my $format = shift; my $fh = $self->{SourceFile}; my $string = sprintf $format, @_; return length $string if(print $fh $string); return -1; } }

      Although, to be honest, the return code from the function probably doesn't matter. I've left it in as a strict interpretation of the OP would mandate it, but likely we could bypass the intermediate sprintf and just printf directly to the output, returning the boolean value that printf returns. It would change the signature by a small bit, but it would probably be a good bit. ;-) Strict porting isn't that great of an idea in the long term anyway.

        Hi,

        Oh, yeah, I forgot the ++ from the C ;-)

        Regards,

        |fire| at irc.freenode.net