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

Hi, I want to call a dll, which requires a pointer to an array of doubles, followed by the length, or number of elements, in the array. I've created my object like:

my $obj = Win32::API->new("dll","Function", [P, I], I);

The problem is, I don't know how to set up the array for the call. I've tried:

$arr=pack("d",1) . pack("d",1.5), pack("d",3);

and

@arr=(pack("d3",1,1.5,3))

whatever I try causes perl.exe to crash (ActivePerl 5.6.1). Any ideas on how the call should be made would be appreciated

Replies are listed 'Best First'.
(tye)Re: Calling win32:api dll with pointer to array
by tye (Sage) on Jan 14, 2002 at 19:36 UTC

    Well, you were close with both of your attempts. Change one comma to a period in your first try and you have something that should work:     $arr= pack("d",1) . pack("d",1.5) . pack("d",3); which can more compactly be written as your second try with @ changed to $:     $arr= pack("d3",1,1.5,3); or, to be more flexible:

    my @arr= ( 1, 1.5, 3 ); my $arr= pack "d*", @arr; my $res= $obj->Call( $arr, 0+@arr );

    An array of doubles in C is simply a bunch of doubles packed right next to each other in a contiguous span of memory. In Perl, the way to get a contiguous span of memory is in a string, so that is what pack produces.

            - tye (but my friends call me "Tye")
      Thanks guys

      it works now

Re: Calling win32:api dll with pointer to array
by larryk (Friar) on Jan 14, 2002 at 18:51 UTC
    From perldoc Win32::API:
    The third parameter, the input parameter list, specifies how many arguments the function wants, and their types. It MUST be passed as a list reference. The following forms are valid: [a, b, c, d] \@LIST
    so make up a reference to an anonymous list as:
    my $arr = [ pack("d",1), pack("d",1.5), pack("d",3) ]; # or as I would do it... my $arr = [ map { pack 'd', $_ } ( 1, 1.5, 3 ) ];
    The [] square brackets make an anonymous array so the scalar $arr (which you need to supply to the Call method of Win32::API) contains a reference to that array.

    You could as easily do:

    my @arr = map { pack 'd', $_ } ( 1, 1.5, 3 );
    and then pass a reference to the list (\@arr) - whichever you prefer.

    Hope this helps

       larryk                                          
    perl -le "s,,reverse killer,e,y,rifle,lycra,,print"
    

      No, the documentation that you quote is talking about the third argument to the new() method, which certain shouldn't contain packed double values. It is talking about the argument [P, I] in the code above.

      The array of doubles is an argument to the C API being accessed and so gets passed in via the Call() method.

      Note that I avoid using the style found in the Win32::API documentation and would rewrite the code as:     my $obj= Win32::API->new( "dll", "Function", [qw( P I )], 'I' ); so that I could use strict with it.

              - tye (but my friends call me "Tye")