I don't have a C string that's terminated by null. I have a CArray[int16] of length 260 that's passed to and filled in by the windows api.
https://docs.microsoft.com/en-us/windows/win32/api/tlhelp32/nf-tlhelp32-createtoolhelp32snapshot https://docs.microsoft.com/en-us/windows/win32/api/tlhelp32/nf-tlhelp32-process32first https://docs.microsoft.com/en-us/windows/win32/api/tlhelp32/nf-tlhelp32-process32next Take the following for example which I quickly whipped up that is supposed to iterate over the processes running on the given windows machine: ------------------------------------------------------------- use NativeCall; constant \MAX_PATH = 260; constant \TH32CS_SNAPPROCESS = 0x00000002; class PROCESSENTRY32 is repr('CStruct') { has int32 $.dwSize; has int32 $.cntUsage; has int32 $.th32ProcessID; has int32 $.th32DefaultHeapID; has int32 $.th32ModuleID; has int32 $.cntThreads; has int32 $.th32ParentProcessID; has int32 $.pcPriClassBase; has int32 $.dwFlags is rw; HAS uint16 @.szExeFile[MAX_PATH] is CArray; }; sub CreateToolhelp32Snapshot(int32, int32 --> Pointer) is native('Kernel32') { * }; sub Process32First(Pointer, Pointer --> Bool) is native('Kernel32') { * }; sub Process32Next(Pointer, Pointer --> Bool) is native('Kernel32') { * }; my $ptr = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); die 'Failed to retreive process list.' if $ptr == Bool::False; my PROCESSENTRY32 $entry .= new(:dwSize(nativesizeof(PROCESSENTRY32))); die 'Unable to iterate over process list' if Process32First($ptr, nativecast(Pointer, $entry)) == Bool::False; repeat { say $entry.szExeFile[0].ord; say $entry.szExeFile[1].ord; } while Process32Next($ptr, nativecast(Pointer, $entry)); ------------------------------------------ The output of the above is: 48 48 This is clearly wrong. This is either a) my misunderstanding of these api calls b) raku bug or c) a usage error on my part. ~Paul On Sun, Jan 3, 2021 at 2:12 AM ToddAndMargo via perl6-users < perl6-us...@perl.org> wrote: > On 1/2/21 8:13 PM, Paul Procacci wrote: > > What I'm trying to attempt to do now is display the contents of that > > CArray (raku member a). In my mind, this is an "array of utf16LE byte > > sequences terminated by 0". > > Hi Paul, > > If I understand your problem, you are having trouble > extracting something usable from Windows return UTF16 > string. > > I have a series of modules I wrote to read and write > to the Windows registry. The strings I got back were > all "UTF16 little ending C Strings". > > This means that every character is a TWO byte word > (16 bits) with the first byte containing the low > value byte. And they terminate with both bytes > being a numerical zero. It is a little weird to get > use to. > > There was some interesting conversation in these > parts a bit ago as to if a C string could ever > not be terminated with a nul. They are always > terminated with a nul. > > The following is from one of the modules I wrote to > support this. I used brute force, rather than > rely on UTF conversion utilities as I found them > unreliable. > > If you un-comment > # print $CStr[ $i ] ~ "," ~ $CStr[ $i + 1 ] ~ ", "; > you can watch the sub do its thing. > > I have a sub to go the other way too, if you want it. > > HTH, > -T > > > > use NativeCall; > > sub c-to-raku-str( BYTES $CStr ) returns Str is export( :c-to-raku-str ) { > # Note: C Strings are always terminated with a nul. This sub will > malfunction without it. > # Note: presumes a UTF16 little endian C String and converts to UTF8 > > my Str $SubName = &?ROUTINE.name; > my Str $RakuStr = ""; > my Str $Msg = ""; > my uint32 $CStrElems = $CStr.elems; > # say $CStrElems; > > loop (my $i = 0; $i < $CStrElems - 2 ; $i += 2) { > if $CStr[ $i ] == 0 && $CStr[ $i + 1 ] == 0 { last; } > > if $i == $CStrElems - 4 { > $Msg = "$SubName ERROR:" ~ " C Strings are required to be > terminated with a nul\n\n" ~ > " Returning an empty string\n" ~ > " Cowardly existing\n"; > exit; > } > > # print $CStr[ $i ] ~ "," ~ $CStr[ $i + 1 ] ~ ", "; > $RakuStr ~= chr( $CStr[ $i ] ); > } > # say ""; > > # say "$RakuStr"; > return $RakuStr; > } > > > -- __________________ :(){ :|:& };: