Skip to content

Instantly share code, notes, and snippets.

@Xliff
Last active May 4, 2016 21:38
Show Gist options
  • Save Xliff/11acc06d8e4c35140fa3535bbfe47329 to your computer and use it in GitHub Desktop.
Save Xliff/11acc06d8e4c35140fa3535bbfe47329 to your computer and use it in GitHub Desktop.

SOLVED

Trying to get this to bind properly with Perl6, and it's being difficult!

#include <stdlib.h>
#include <stdio.h>

int floatArrayTest(float **pa) {
  *pa = malloc(sizeof(float *) * 500);
  float *pac = *pa;
  if (pac == NULL) {
   return -1;
  }

  int i;
  for (i = 0; i < 500; i++) {
   pac[i] = i + 0.5f;
  }

  return 0;
}

int pointerArrayTest(float ***pa) {
  //printf("pa is %x\n", pa);

  *pa = (float **)malloc(sizeof(float **) * 5);
  float **pac = *pa;
  if (pac == NULL) {
   return -1;
  }

  int c;
  int v = 0;
  for (c = 0; c < 5; c++) {
   pac[c] = (float *)malloc(sizeof(float) * 500);
   if (pac[c] == NULL) {
    return -1;
   }
   
   int s;
   for (s = 0; s < 500; s++) {
    pac[c][s] = v++;
   }
  }

  return 0;
}

My first attempt was the following:

#!/usr/bin/perl6

use v6;
use NativeCall;

sub floatArrayTest(CArray[num32] is rw)
 is native('./03-read-vorbis.so')
 returns int32
 { * };

sub pointerArrayTest(CArray[CArray[num32]] is rw)
 is native('./03-read-vorbis.so')
 returns int32
 { * };

my $appp = CArray[CArray[num32]].new();
$appp[$_] = CArray[num32].new(Num(0.0)) for ^5;

say "Calling C routine...";
my $ret = pointerArrayTest($appp);
die 'Borkage in C Lib!' unless $ret == 0;
say "Routine returned with code {$ret}...";
say "\$appp Defined: {$appp.defined}";
say $appp.WHAT;

for (^5) -> $c {
 say "C: $c";
 say "\$appp[$c] Defined: {$appp[$c].defined}";
 next unless $appp[$c].defined;
 say "\$appp[$c] = {$appp[$c]}";
 my $chan_a = nativecast(CArray[num32], $appp[$c]);
 
 for (^500) -> $s {
  say "chan_a[$s]: {$chan_a[$s]}";
 }
 
 last;
}

Which didn't give me the expected output. The 2D array should contain the numbers 0-2499 over 5 float arrays.

Here's what did work:

#!/usr/bin/perl6

use v6;
use NativeCall;

sub pointerArrayTest(Pointer is rw)
    is native('./03-read-vorbis.so')
    returns int32
    { * };

my Pointer $appp .= new;

say "Calling C routine...";
my $ret = pointerArrayTest($appp);
die 'Borkage in C Lib!' unless $ret == 0;
say "Routine returned with code {$ret}...";

my @ap := nativecast(CArray[CArray[num32]], $appp);

my @chan_a := nativecast(CArray[num32], @ap[4]);

for (450..499) -> $s {
    say "chan_a[$s]: {sprintf "%.0f", @chan_a[$s]}";
}

Here's the output, which is correct:

Calling C routine...
Routine returned with code 0...
chan_a[450]: 2450
chan_a[451]: 2451
chan_a[452]: 2452
chan_a[453]: 2453
chan_a[454]: 2454
chan_a[455]: 2455
chan_a[456]: 2456
chan_a[457]: 2457
chan_a[458]: 2458
chan_a[459]: 2459
chan_a[460]: 2460
chan_a[461]: 2461
chan_a[462]: 2462
chan_a[463]: 2463
chan_a[464]: 2464
chan_a[465]: 2465
chan_a[466]: 2466
chan_a[467]: 2467
chan_a[468]: 2468
chan_a[469]: 2469
chan_a[470]: 2470
chan_a[471]: 2471
chan_a[472]: 2472
chan_a[473]: 2473
chan_a[474]: 2474
chan_a[475]: 2475
chan_a[476]: 2476
chan_a[477]: 2477
chan_a[478]: 2478
chan_a[479]: 2479
chan_a[480]: 2480
chan_a[481]: 2481
chan_a[482]: 2482
chan_a[483]: 2483
chan_a[484]: 2484
chan_a[485]: 2485
chan_a[486]: 2486
chan_a[487]: 2487
chan_a[488]: 2488
chan_a[489]: 2489
chan_a[490]: 2490
chan_a[491]: 2491
chan_a[492]: 2492
chan_a[493]: 2493
chan_a[494]: 2494
chan_a[495]: 2495
chan_a[496]: 2496
chan_a[497]: 2497
chan_a[498]: 2498
chan_a[499]: 2499

After further experimentation and experience with NativeCall, it turns out that the first call to nativecast() is all that is necessary. Instead of:

my @ap := nativecast(CArray[CArray[num32]], $appp);

my @chan_a := nativecast(CArray[num32], @ap[4]);

for (450..499) -> $s {
    say "chan_a[$s]: {sprintf "%.0f", @chan_a[$s]}";
}

Use this:

my @ap := nativecast(CArray[CArray[num32]], $appp);
for (450..499) -> $s {
    say "chan_a[$s]: {sprintf "%.0f", @ap[4][$s]}";
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment