in reply to Re: Passing a bytestring from Perl to Inline::C as a 2d array
in thread Passing a bytestring from Perl to Inline::C as a 2d array

pack "I*", (0) x ( $x_dimension x $y_dimension );

int **table = ( int ** ) byte_string;

  table[ i ][ j ]++;

That still won't work and cannot be made to work! You will still get segfaults.

You cannot cast a 1D array point to a 2D array of arrays pointer. Full stop.

The memory for a 1D array (as produced by pack) is laid out so:

----------------------------....--------------------- ...|int1|int2|int3|int4|int4|....|N-3 |N-2 |N-1 |N | ----------------------------....---------------------

For a 2D array like so:

---- ptr | This is the int** ---- ... it points to an array of pointer below ... with one pointer for each of the first dimension --------------------------------------- ptr0|ptr1|ptr2|ptr3|....|Y-2 |Y-1 |Y | Each if these is an int * --------------------------------------- ... And each of those pointer point to contingous 1D arrays of ints ... each the size of the second dimension ... that can (and usually are) distributed at disparate position in me +mory ... and in no particular positions, even before the above block of ram +. --------....-----.....-----...etc |ary4| |ary2| |ary0| --------....-----.....-----...etc

There is simply no way to cast from one to the other.


Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
RIP PCW It is as I've been saying!(Audio until 20090817)

Replies are listed 'Best First'.
Re^3: Passing a bytestring from Perl to Inline::C as a 2d array
by Marshall (Canon) on Nov 14, 2009 at 15:35 UTC
    I think BrowserUk is spot on! There is a problem with the C code and the interface.

    I am still troubled by the whole concept of the OP's approach. Instead of packing some things ("chars") into words for C to access on a byte per byte basis, run some regex or other Perl operation on those "things" and THEN run pack() if you need to! I see no need for 'C' here.

    Perl has a very efficient char per char replacement operator called "tr". And also, 'a' + 1 REALLY does mean "b"! Just like in 'C'. I think that if we get to the real requirement, we will find that Perl will do it just fine. The sub() appears trivial enough that I see no need to go through the hassle of interfacing 2 languages.

      Instead of packing some things ("chars") into words for C to access on a byte per byte basis

      He's not packing "chars". He's packing integers (note the 'I*' pack template). And whilst his sample code shows him just incrementing those integers (which he is initialising to 0), his description points out that he intends to populate the structure with "scores", which he is presumably obtaining from somehwere where they must be accessed via C.


      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.
        Well, "I" means unsigned int with some variability in size.. But no matter..if these scores are that big (>=4 bytes), then why even bother with pack()? Pass around something (update: "something" here means pointer to a hunk of memory) that is X x Y ints big which is what I suggest even if the scores are as small as 8 bits.

        I am also challenging the need for 'C' in the first place. There may some false assumption about Perl math performance. Yes, Perl is far slower than 'C', but its not 20x slower and actually does surprisingly well on "int" operations.

        Update:

        I see how I got onto this "char" idea, it was from the byte_stream name and I remembered the "byte" part. Continuing on with this "compact" requirement...let's say we have 1 million 1 byte integers. That takes 4MB on my 32 bit machine. What will happen if we "pack" that? It will take even MORE memory! pack() will not overwrite the original 4MB and will use 1MB more for the "packed" version. The percentage growth in memory usage is even worse if these are 16 bit integers. As far as speed goes, there are some complex "yeah but's" that depend upon how good your memory sub-system is. However it is hard for me to imagine how "packing" could work out well.

        In short: if you have a memory structure that you want to send to some sub(), "packing" is literally a waste of time and memory. Send a pointer to the memory structure that you already have. In general (I don't know a case where this is not true) your Perl environment will have the same understanding as your 'C' environment regarding how big an "int" is...32 or 64 bits. The 16,24,48 bit systems have gone the way of the dodo bird.