El mar., 31 dic. 2019 a las 21:56, ToddAndMargo via perl6-users (< perl6-us...@perl.org>) escribió:
> On 2019-12-31 09:17, JJ Merelo wrote: > > Hi, > > > > El mar., 31 dic. 2019 a las 5:54, Todd Chester via perl6-users > > (<perl6-us...@perl.org <mailto:perl6-us...@perl.org>>) escribió: > > > > Hi All, > > > > > https://docs.raku.org/language/nativecall.html#Passing_and_returning_values > > > > Did anyone else discover the mistake, hopefully not the hard way > like I > > did. Anyone get weird gibberish printed out like I did? > > > > my$string="FOO"; > > > # The lifetime of this variable must be equal to the required lifetime of > > # the data passed to the C function. > > my$array=CArray[uint8].new($string.encode.list);v > > > > The mistake is that "C" strings are terminated by a chr(0) -- in > > "C" terms chr(0) is called a nul or 0x00. > > > > If you don't terminate your C string, the reading functions keep > > careening > > until it finds a chr(0). You have to tack a chr(0) onto the end. > > > > my$array=CArray[uint8].new($string.encode.list); > > $array [$array.elems] = 0; > > > > $array should be 70 79 70 0 not 70 79 79 > > You can test this with `say "$array"` (include the quotes). > > > > Maybe JJ will pick up on this and get it fixed. > > > > > > > > I don't always read this list, but I do read issues. If you put it > > there, it will be definitely get addressed when possible. > > > > -- > > JJ > > > Hi JJ, > > I have a rule about not posting to that list, so maybe > I could answer that with I will not address issues that are not raised in the GitHub repo (which is not a list, BTW), but anyway, here you go. The thing is, first, that the example has little to do with the structure of the string itself; it focuses on the fact that the string has to be encoded. But anyway, let's check if that is true, with this little example: ------ >8 ---------- const-char.c ---------------------- #include <stdio.h> void set_foo ( const char *foo) { printf("%s", foo); } ----------------- 8< -------------------------------------- And this Raku script that uses it -------------------------- >8 --------------- null-terminated-or-not.p6 -------------- use NativeCall; my $string = "FOO"; my $array = CArray[uint8].new($string.encode.list); sub set_foo(CArray[uint8]) is native('const-char') { * } set_foo( $array ); ----------------- 8< -------------------------------------- This works without a glitch, printing FOO to the terminal. As a matter of fact, $array.elems returns 3, so its "encode" is not actually adding any null-termination at the end. I'm no expert in C myself, and have not been for at least 25 years. But I know stackoverflow, which says ( https://stackoverflow.com/a/1253336/891440) Why do C strings work this way? It's because the PDP-7 microprocessor, on which UNIX and the C programming language were invented, had an ASCIZ string type. ASCIZ meant "ASCII with a Z (zero) at the end." Is this the only way to store strings? No, in fact, it's one of the worst ways to store strings. For non-trivial programs, APIs, operating systems, class libraries, you should avoid ASCIZ strings like the plague. Plagues are bad. Let's avoid them for the upcoming year. Other than that, happy new year to every one. -- JJ