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

Is there any way to make the ST() argument stack look like a double *?

I've spent the last 3 hours reading basically the same informatoin in a dozen different tutorials.

I want to pass an array @a = (0.3, 0.2, 0.4) to a C function. Normally that's really easy:

void something(a,b,c) double a double b double c
That actuall turns into (in the .c):
double a = (double) SvNV( ST(1) ); double b = (double) SvNV( ST(2) ); double c = (double) SvNV( ST(3) );

But what if the C library function expected an array of doubles (double *)? All I can think to do is make an array, and copy the data into it and pass that. Which is a waste, since the function something is obviously going to iterate over it again....

Is there any way to make the ST() argument stack look like a double *?

void something(array) double * array CODE: array = (double *) (MAJIK_STUFF(ST))

Replies are listed 'Best First'.
(tye)Re: double array in XS
by tye (Sage) on Nov 02, 2000 at 21:36 UTC

    My advice is almost always the same when someone asks how to do something in XS code: Don't! Do it in Perl code where it is much easier to write, understand, debug, extend, etc. For example:

    sub something { croak "Usage: ",__PACKAGE__,"::something( $a, $b, $c )" unless 3 == @_; my $cArray= pack( "d*", @_ ); _something( $cArray ); }
    along with
    void _something( cArray ) char * cArray; CODE: something( (double *)cArray );

    There are actually ways to look through a Perl array and build this "packed", C-style array of doubles in XS code. They aren't horribly complicated in this specific case, but I don't know what they are because I don't really want to know because I find the Perl solution so much superior.

    When writing XS code, I strive to make the XS interface minimal and very C-like and wrap that in Perl code that provides the rich interface that the module user will see.

    I find that this approach leads to both more powerful and more efficient modules.

    The one exception has been processing of SV buffers since you can't do these things portably in Perl code:

    • Determine the current allocated size of an SV's PV buffer
    • Grow the SV's PV buffer without changing the SV's value

    I've been considering writing an XS module that lets me do these things in Perl and then moving the buffer allocation code of my other XS modules out of XS and back into Perl because the complexity of the buffer allocation code is a problem since XS code is so hard to debug. ):

            - tye (but my friends call me "Tye")
Re: double array in XS
by fred (Acolyte) on Nov 02, 2000 at 19:58 UTC
    I'm afraid I don't know enough about XS to tell you whether there is a way to do it directly.

    However, it's likely that the time required to copy the array is negligibile compared to the time required to execute the library call. Iterating over an array twice is not significantly worse than iterating over it once. (2X at worst, not taking into account the effects of the cache)

    If, on the other hand, the c function is something like a binary search that doesn't iterate over the entire array, and the size of your array is large, then you may need to be concerned.
Re: double array in XS
by Fastolfe (Vicar) on Nov 02, 2000 at 20:39 UTC
    Like fred, I'm not 100% sure how to help you; others here may know XS better than I, but I would consider writing a wrapper function that took in all 3 arguments (or more?) and called the appropriate C function correctly.
Re: double array in XS
by jettero (Monsignor) on Nov 02, 2000 at 21:32 UTC
    Here's my actual working XSUB btw:
    void something(input, ...) CODE: double *input = (double *) alloca((sizeof(double)) * (items-1) +); for(int i=0; i<(items-1); i++) input[i] = (double) SvNV(ST(i+1)); THIS->something(input);

      Note that alloca() is not as portable as one might hope. I find it very useful in XS code, but avoid it (now) because it would make my modules less portable. ):

      I try to replace it with creating SVs with PV buffers of the proper size and letting Perl's garbage collection free the buffers for me.

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