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]}";
}