http://qs1969.pair.com?node_id=1180124


in reply to Is this a sane/safe way to pass an aref into a C function?

XS code is much more likely to be buggy and fragile than Perl code. If you want to pass a list of bytes from Perl to C, then you would be better off doing it as a data structure that doesn't require your C code to try to deal with Perl data structures. This will also have the side-effect of you having less XS code, which will reduce how many bugs you have to fix and how long it will take you to fix the bugs you have.

So just use:

... my $str = pack "U0C*", @bytes; testing( $channel, $str, length($str) ); ... int testing( in­t channel, char* buf, int len ) {

- tye        

Replies are listed 'Best First'.
Re^2: Is this a sane/safe way to pass an aref into a C function? (XS<Perl)
by stevieb (Canon) on Jan 22, 2017 at 18:15 UTC

    Thanks tye, that's great!

    I was trying similar things, but did not realize pack was required. This is far easier and less error-prone as you said (as well it saves me from having to wrap one C function with another as this way, I can pass the data directly to the original function), but I am thankful that I was able to learn how to pass in perl variables into a C function, even though I'm going to revert to using this method instead:

    use warnings; use strict; use feature 'say'; use Inline 'C'; my @b = (1..3, 253..255); my $x = pack "V0C*", @b; check($x, length($x)); __END__ __C__ #include <stdio.h> #include <stdint.h> void check(unsigned char* n, int len){ int i; for(i=0; i<len; i++){ printf("%d\n", n[i]); } }

    Output:

    1 2 3 253 254 255

    Of course, in the real code, I perform error checking.

      Good thread.
      I tried to get this code working with Active State 5.20, but I don't have right "formula" to do that on my current little laptop. Is there a FAQ on this? What compiler is necessary, etc...?

      PS: I think your check() would be more "C like" coded something like this:

      void check(unsigned char* n, int len) { while (len--) { printf ("%d\n", *n++); } }
      The variable: int i is unnecessary. With the C calling convention on 32 bit machine, check() is passed a 32 bit pointer to n (pointer to an array of unsigned bytes) and a 32 bit signed integer, len on the stack. These are copies for the subroutine to modify and use as it wishes.

      This n[i] syntax is often coded by the compiler as (n i*size_of_n) plus base address. Whereas n++ is coded as n plus the size_of_n.