In working on trying to write Perl6 library bindings for libogg, I ran into this interesting problem.
How would you represent this piece of a struct in NativeCall:
unsigned char header[282]
Turns out that this is one of the shortcomings of NativeCall.
Until Perl6 can adequately represent pre-defined character arrays, you can do something like this:
class ogg_stream_state_header is repr('CStruct') {
has uint64 $.header00;
has uint64 $.header01;
has uint64 $.header02;
has uint64 $.header03;
has uint64 $.header04;
has uint64 $.header05;
has uint64 $.header06;
has uint64 $.header07;
has uint64 $.header08;
has uint64 $.header09;
has uint64 $.header10;
has uint64 $.header11;
has uint64 $.header12;
has uint64 $.header13;
has uint64 $.header14;
has uint64 $.header15;
has uint64 $.header16;
has uint64 $.header17;
has uint64 $.header18;
has uint64 $.header19;
has uint64 $.header20;
has uint64 $.header21;
has uint64 $.header22;
has uint64 $.header23;
has uint64 $.header24;
has uint64 $.header25;
has uint64 $.header26;
has uint64 $.header27;
has uint64 $.header28;
has uint64 $.header29;
has uint64 $.header30;
has uint64 $.header31;
has uint64 $.header32;
has uint64 $.header33;
has uint64 $.header34;
has uint8 $.header35;
method as_blob {
my @uint64_list = (
$.header00,
$.header01,
$.header02,
$.header03,
$.header04,
$.header05,
$.header06,
$.header07,
$.header08,
$.header09,
$.header10,
$.header11,
$.header12,
$.header13,
$.header14,
$.header15,
$.header16,
$.header17,
$.header18,
$.header19,
$.header20,
$.header21,
$.header22,
$.header23,
$.header24,
$.header25,
$.header26,
$.header27,
$.header28,
$.header29,
$.header30,
$.header31,
$.header32,
$.header33,
$.header34
);
my @b;
for @uint64_list -> $u {
# cw: Break the uint64 into 8 uint8 chunks.
my $ca = Buf[uint8].new(
nativecast(CArray[uint8], array[uint64].new($u)[^8]
);
for ^8 -> $i {
@b.push($ca[$i]);
}
}
@b.push($.header35);
# Return BLOB containing assembled 282 byte header.
return Blob.new(@b);
}
}
sortis from #perl6 provided this, more elegant, version:
# sortiz++
method as_blob2 {
return Blob[uint8].new(
nativecast(CArray[uint8], self)[
^nativesizeof(ogg_stream_state_header)
]
);
}
Hope this gets solved, soon. 282 bytes was manageable, but 2820 bytes is another matter entirely.
Thanks to #perl6's timotimo for this suggestion.