Nicholas Clark wrote:
>
> I think that it's possible to partly work round this by prototyping your
> function (at the perl level), but in turn I don't think that Inline can do
> this; you'd need XS.
>
> But even that doesn't really solve the problem at perl level, as
> @a = (%d\n%#o\n", $x, $y);
> wrap_printf(@a);
>
> would work correctly with @a actually passed in as [EMAIL PROTECTED], but
> wrap_printf("%d\n%#o\n", $x, $y);
>
> wouldn't. (I think. Sorry, this is untested)
>
> And as the rest of the thread discusses, even this doesn't solve the problem
> of generating a va_arg list. Which I think can't be done portably (ie without
> cheating).
Which, presumably, is why the Inline C-Cookbook uses the Inline::C stack macros (rather than the va_list macros) to extract the arguments from a variable length argument list :-)
I've decided to use perl to parse the arguments, breaking them up into a series of ($format, $variable) pairs. Then it's just a matter of calling wrap_printf($format, $variable) for each of the pairs. This means that instead of the Inline::C function receiving a variable length argument list, the argument list is fixed at 2 - which gets rid of all of those nasty problems.
ie: wrap_wrap_printf("The %s is between %d%% and %d%%\n",'percentage',6,9); gets implemented as something like:
wrap_printf("The %s is between ", 'percentage'); wrap_printf("%d%% and ", 9); wrap_printf("%d%%\n", 15);
Well ... perl is supposed to be good at parsing strings, isn't it .... unfortunately I don't totally trust *my* capacity to code such parsing of format strings correctly - which is why I initially shyed (shied ?) away from that approach.
One problem with this approach is that the following won't work (because it needs an argument list 3 items long):
wrap_wrap_printf("The float is %.*f\n", $places, $float);
There may be other shortcomings which I'll eventually stumble over. I'm not going to bother about the shortcoming I've just illustrated because, in perl, it's quite trivial to rewrite it in a 2-argument form (which will work fine):
wrap_wrap_printf("The float is %.${places}f\n", $float);
Thanks for all of the thoughts on this. It has been quite educational.
Cheers, Rob