Q: Parsing string into ARGV equivalent (Windows and Perl) Edit - Answer posted below
I have a script that usually uses @ARGV arguments but in some cases it is invoked by another script (which I cannot modify) that instead only passes a config filename which among other things has the command line options that should have been passed directly.
Example:
Args=--test --pdf "C:\testing\my pdf files\test.pdf"

If possible I'd like a way to parse this string into an array that would be identical to @ARGV.
I have a workaround where I setup an external perl script that just echos @ARGV, and I invoke this script like below (standard boilerplate removed).
echo-args.pl
print join ("\n", @ARGV);

test-echo-args.pl
$my_args = '--test --pdf "C:\testing\my pdf files\test.pdf"';
@args = map { chomp ; $_ } `perl echo-args.pl $my_args`;

This seems inelegant but it works. Is there a better way without invoking a new process? I did try splitting and processing but there are some oddities on the command line e.g. -a"b c" becomes '-ab c' and -a"b"" becomes -ab" and I'd rather not worry about edge cases but I know that'll bite me one day if I don't.

A: Answer - thanks ikegami!
I've posted a working program below that uses Win32::API and CommandLineToArgvW from shell32.dll based on ikegami's advice. It is intentionally verbose in the hopes that it'll be more easy to follow for anyone like myself who is extremely rusty with C and pointer arithmetic.
Any tips are welcome, apart from the obvious simplifications :)
use strict;
use warnings;

use Encode     qw( encode decode );
use Win32::API qw( );
use Data::Dumper;

# create a test argument string, with some variations, and pack it
# apparently an empty string returns $^X which is documented so check before calling
my $arg_string = '--test 33 -3-t"  "es 33\t2 ';
my $packed_arg_string = encode('UTF-16le', $arg_string."\0");

# create a packed integer buffer for output
my $packed_argc_buf_ptr = pack('L', 0);

# create then call the function and get the result
my $func = Win32::API->new('shell32.dll', 'CommandLineToArgvW', 'PP', 'N')
   or die $^E;
my $ret = $func->Call($packed_arg_string, $packed_argc_buf_ptr);

# unpack to get the number of parsed arguments
my $argc = unpack('L', $packed_argc_buf_ptr);
print "We parsed $argc arguments\n";

# parse the return value to get the actual strings
my @argv = decode_LPWSTR_array($ret, $argc);
print Dumper \@argv;

# try not to leak memory
my $local_free = Win32::API->new('kernel32.dll', 'LocalFree', 'N', '')
    or die $^E; 
$local_free->Call($ret);

exit;

sub decode_LPWSTR_array {
    my ($ptr, $num) = @_;

    return undef if !$ptr;

    # $ptr is the memory location of the array of strings (i.e. more pointers)
    # $num is how many we need to get
    my @strings = ();

    for (1 .. $num) {
        # convert $ptr to a long, using that location read 4 bytes - this is the pointer to the next string
        my $string_location = unpack('P4', pack('L', $ptr));        
        # make it human readable
        my $readable_string_location = unpack('L', $string_location);       
        # decode the string and save it for later
        push(@strings, decode_LPCWSTR($readable_string_location));

        # our pointers are 32-bit
        $ptr += 4;      
    }
    return @strings;
}

# Copied from http://stackoverflow.com/questions/5529928/perl-win32api-and-pointers
sub decode_LPCWSTR {
   my ($ptr) = @_;

   return undef if !$ptr;

   my $sW = '';
   for (;;) {
      my $chW = unpack('P2', pack('L', $ptr));
      last if $chW eq "\0\0";
      $sW .= $chW;
      $ptr += 2;
   }

   return decode('UTF-16le', $sW);   
}


A: In unix systems, it's the shell that parses that shell command into strings. But in Windows, it's up to each application. I think this is normally done using the CommandLineToArgv system call (which you could call with the help of Win32::API), but the spec is documented here if you want to reimplement it yourself.
