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

Here is my code:
use Win32::API; #setup DLL $PGetAddress = Win32::API->new('IBKGetAddress2.dll', 'GetAddress', 'PP +', 'P'); if(not defined $PGetAddress) { die "Can't import API : $!\n"; } $Address="419 w 154"; $ZipCode="10032"; $return=$PGetAddress->Call($Address,$ZipCode)||die "Can't run API $!\n +";; print "Output: $return\n"; print "Output Length: ".length($return)."\n";
Runing AS Perl 5.8.6.
The return from the VB DLL is a 1000 character string with a valid US Postal address. However I can only read the first letter of the return string. Do I need to Pack and Unpack? Not sure how to continue. Thanks for the help.

Replies are listed 'Best First'.
Re: Win32::API returns 1 character when reading a VB DLL ("UNICODE")
by tye (Sage) on Jul 22, 2005 at 14:44 UTC

    Win32::API's "P" will copy the "string" up to the first '\0'. It sounds like you have a (what Microsoft calls) "UNICODE" string (16-bit characters), so you've got something like "s\0t\0r\0i\0n\0g\0\0\0". So you can't use Win32::API's "P" since then only "s\0" gets copied.

    But if that is the case, then you are probably supposed to pass in 16-bit-character strings as well. Which means something similar to (I can't really test this since I don't have your *.dll):

    #!/usr/bin/perl -w use strict; use Win32::API; my $PGetAddress = Win32::API->new( 'IBKGetAddress2.dll', 'GetAddress', 'PP', 'N' ) or die "Can't import API : $!\n"; my $Address = pack "S*", unpack("C*","419 w 154"), 0; my $ZipCode = pack "S*", unpack("C*","10032"), 0; my $return = $PGetAddress->Call( $Address, $ZipCode ) or die "Can't run API: $! ($^E)\n"; my $string = pack "C*", unpack "S*", unpack "P2000", pack "L", $return +; $string =~ s/\0.*//s; print "Output: ($string)\n";

    If you've got a variable-length output string, then things get really ugly.

    But this is all just guessing.

    Oh, and by way of explanation, the first two strings of pack/unpack convert 8-bit-character strings into 16-bit-character strings. The last string of pack/unpack goes like this:

    Make what looks like a C struct containing the pointer that was returned:
        pack "L", $return;
    Copy into a Perl string the 2000 bytes which that pointer points to:
        unpack "P2000",
    Get the list of numbers from treating each pair of bytes (16 bits) as a number:
        unpack "S*",
    Build a string from those numbers:
        my $string = pack "C*",
    Remove the terminating '\0' and anything after it:
        $string =~ s/\0.*//s;

    - tye