Hi David,

the first thing that catches my eye is that your struct and the class
have the members switched around, so you're already almost guaranteed to
read a bogus pointer when trying to get the data.

Also, please note that returning structs directly, or passing structs
directly, as arguments is hairy business, you'll probably want to work
with pointers instead, which either means your function has to malloc
the EncodedData struct, or take a pointer to an already created one as
an argument - you would then create the EncodedData on the raku side
with a .new

Whenever you declare a struct to be passed as argument or received as
return value in NativeCall, you will get "TheStruct *" on the C side.

Not sure if that's all it takes to fix this. Feel free to write back to
the list.

Hope to Help
  - Timo

On 08/05/2020 12:44, David Santiago wrote:
> Hello,
>
> I'm porting some personal perl5 scripts to Raku, and  one of those
> scripts  is using Inline::C.
>
> The inline::c code would contain a function with the signature:
>
> AV* encode(unsigned char* data, size_t data_size)
>
> Description of the parameters on the original perl script:
> data -> binary string (the value comes from read $FH)
> data_size -> size in bytes of binary_string (the value comes from the
> return of the read function)
>
> And it would return an array with two values (a binary string and its crc32):
>
> """
> SV* enc_string = newSVpv(buffer, 0);
> SV* ret = sv_2mortal(newAV());
> av_push(ret, enc_string);
> SV* hex_string = newSVpv(hex_number, 0);
> av_push(ret, hex_string);
> free(hex_number);
> return ret;
> """
>
>
> Now for using it in raku, i'm changing  the return value to a struct:
> typedef struct{
>   unsigned char* data;
>   uint32_t crc32;
> } EncodedData;
>
> So i changed the signature to:
> EncodedData encode(unsigned char* data, size_t data_size)
>
> And i'm returning the struct:
> """
> EncodedData ed;
> ed.crc32 = crc32;
> ed.data = encbuffer;
>
> return ed;
> """
>
> Create a shared lib gcc -shared -olibmylib.so mylib.c
>
> Now on my raku script i did:
> """
> class EncodedData is repr('CStruct') {
>     has uint32 $.crc32;
>     has str $.data;
> }
>
> sub MAIN() {
>     sub encode(str $data, size_t $size --> EncodedData) is
> native('lib/MyLib/libmylib.so') {*};
>     my EncodedData $ed = encode("this is my string that will be
> encoded", "this is my string that will be encoded".chars );
>     say $ed.crc32.base(16);
>     say $ed.data;
> }
> """
> However this isn't working. Everytime i access "$ed.data" I'm getting
> the following error:
> "fish: 'raku bin/uints.p6' terminated by signal SIGSEGV (Address
> boundary error)"
>
> Why? How do i fix it?
>
> Also the read method from the IO::Handle returns a Buf. I would like
> to pass it directly to my C function. Is there any change in the
> C/raku code i should do?
> The data field from class EncodedData is type "str". Should it be
> CArray[uint8] instead?
>
> Best regards,
> David Santiago

Reply via email to