Re: Nativecall - Help with converting wchar_t CArray to something printable
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 = 0x0002; 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-users@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; > } > > > -- __ :(){ :|:& };:
Re: Nativecall - Help with converting wchar_t CArray to something printable
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; }
Re: Nativecall - Help with converting wchar_t CArray to something printable
A follow-up to my initial message. I think the following is relevant: https://github.com/rakudo/rakudo/issues/3633 I think my inlined array is actually being filled with zero's. say $a.a[0]; say $a.a[1]; Yields: 0 0 I'm using the comma ide: >raku -v Welcome to Rakudo(tm) v2020.12. Implementing the Raku(tm) programming language v6.d. Built on MoarVM version 2020.12. ~Paul On Sat, Jan 2, 2021 at 11:13 PM Paul Procacci wrote: > Hey gents (again), > > I'm having on awful time with decoding UTF16LE character sequences that > are placed into a Nativecall CArray that I've defined as an interface > between Raku and a windows library call. > > The structure used by the windows function includes a static wchar_t field > that's PATH_MAX in > length (260 wchar_t's). It would look like the following in C: > > struct Something { > int32_t dwSize; > wchar_t a[260]; > }; > > I've written the following as the Raku counterpart to the above: > > class Something is repr('CStruct') { >has int32 $.dwsize; >HAS int16 @.a[260] is CArray; > }; > > Given the following definition for the windows library call: > > bool Test(Something *x); > > .. I've defined the following on the raku side of things: > > sub Test(Pointer --> Bool) is native('Kernel32') { * }; > > -- > > The function is supposed to write characters into the space allotted, > namely a. > The only required set member prior to calling the subroutine is that the > size of the structure. > It gets set in dwSize like so: > > my Something $a .= new(:dwSize(nativesizeof(Something))); > > Then the actual function call from the raku side of things: > > Test(nativecast(Pointer, $a)); > > -- > > All the above is working. 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". > > What's the cleanest way of doing this in raku? I've tried variations of > "join" and "encode", simple printf's, say's, etc., and even tried > manipulating this data with Buf's, but I can't seem to get it quite right. > > Any help is appreciated. > ~Paul > -- > __ > > :(){ :|:& };: > -- __ :(){ :|:& };:
Nativecall - Help with converting wchar_t CArray to something printable
Hey gents (again), I'm having on awful time with decoding UTF16LE character sequences that are placed into a Nativecall CArray that I've defined as an interface between Raku and a windows library call. The structure used by the windows function includes a static wchar_t field that's PATH_MAX in length (260 wchar_t's). It would look like the following in C: struct Something { int32_t dwSize; wchar_t a[260]; }; I've written the following as the Raku counterpart to the above: class Something is repr('CStruct') { has int32 $.dwsize; HAS int16 @.a[260] is CArray; }; Given the following definition for the windows library call: bool Test(Something *x); .. I've defined the following on the raku side of things: sub Test(Pointer --> Bool) is native('Kernel32') { * }; -- The function is supposed to write characters into the space allotted, namely a. The only required set member prior to calling the subroutine is that the size of the structure. It gets set in dwSize like so: my Something $a .= new(:dwSize(nativesizeof(Something))); Then the actual function call from the raku side of things: Test(nativecast(Pointer, $a)); -- All the above is working. 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". What's the cleanest way of doing this in raku? I've tried variations of "join" and "encode", simple printf's, say's, etc., and even tried manipulating this data with Buf's, but I can't seem to get it quite right. Any help is appreciated. ~Paul -- __ :(){ :|:& };:
Re: NativeCall -- size of data structure
nativesizeof is what I was looking for. Thanks, ~Paul On Sat, Jan 2, 2021 at 8:39 PM ToddAndMargo via perl6-users < perl6-users@perl.org> wrote: > On 1/2/21 4:58 PM, Paul Procacci wrote: > > Hey Gents, > > > > Hopefully a simple question that I could not find the answer to. > > > > Given the following: > > > > class PROCESSENTRY32 is repr('CStruct') { > > has int32 $.dwSize; > > has int32 $.cntUsage; > > has int32 $.th32ProcessID; > > has Pointer $.th32DefaultHeapID; > > has int32 $.th32ModuleID; > > has int32 $.cntThreads; > > has int32 $.th32ParentProcessID; > > has long $.pcPriClassBase; > > has int32 $.dwFlags; > > HAS Str @.szExeFile[260] is CArray;# MAX_PATH on windows is 260 > > Did you mean to capitalize the HAS? > > > }; > > > > > > ... is there is a raku method that gives me the size of this data > structure? > > > > In C for example one would use sizeof() to provide the size. In raku I > > could not find the documentation that would provide this information. > > > > Thanks, > > Paul Procacci > > Hi Paul, > > Not that I know of. Raku has a lot of things in > the background of its structures that C does not. > > C does not have OOP (object orientated programming) > but does have "struct", which is close enough. > > What you are trying to do is match the C structure > of the system call with Raku's OOP "class". In Raku, > "class" is the definition of a structure and not the > structure itself -- very much like C's "struct". > > You don't get an actual structure until you > declare one from the class. For example: > > my $x = PROCESSENTRY32.new; > > And it is going to be a lot bigger behind the scenes > that just adding up the bits. You really do not need > to know the behind the scene details anyway. Raku > strives to remove the need for the programmer to > have to know these kind of details, unlike C. > > What system call are you trying to run? > > I have an example of how to read Windows Time > that also uses OOP (class, object, and method). > Let me know if you want it > > -T > > > > -- __ :(){ :|:& };:
Re: NativeCall -- size of data structure
On 1/2/21 4:58 PM, Paul Procacci wrote: Hey Gents, Hopefully a simple question that I could not find the answer to. Given the following: class PROCESSENTRY32 is repr('CStruct') { has int32 $.dwSize; has int32 $.cntUsage; has int32 $.th32ProcessID; has Pointer $.th32DefaultHeapID; has int32 $.th32ModuleID; has int32 $.cntThreads; has int32 $.th32ParentProcessID; has long $.pcPriClassBase; has int32 $.dwFlags; HAS Str @.szExeFile[260] is CArray;# MAX_PATH on windows is 260 Did you mean to capitalize the HAS? }; ... is there is a raku method that gives me the size of this data structure? In C for example one would use sizeof() to provide the size. In raku I could not find the documentation that would provide this information. Thanks, Paul Procacci Hi Paul, Not that I know of. Raku has a lot of things in the background of its structures that C does not. C does not have OOP (object orientated programming) but does have "struct", which is close enough. What you are trying to do is match the C structure of the system call with Raku's OOP "class". In Raku, "class" is the definition of a structure and not the structure itself -- very much like C's "struct". You don't get an actual structure until you declare one from the class. For example: my $x = PROCESSENTRY32.new; And it is going to be a lot bigger behind the scenes that just adding up the bits. You really do not need to know the behind the scene details anyway. Raku strives to remove the need for the programmer to have to know these kind of details, unlike C. What system call are you trying to run? I have an example of how to read Windows Time that also uses OOP (class, object, and method). Let me know if you want it -T
Re: NativeCall -- size of data structure
Apologies. I just came across it. nativesizeof is the subroutine you're looking for. Again, sorry for the noise. ~Paul On Sat, Jan 2, 2021 at 7:58 PM Paul Procacci wrote: > Hey Gents, > > Hopefully a simple question that I could not find the answer to. > > Given the following: > > class PROCESSENTRY32 is repr('CStruct') { > has int32 $.dwSize; > has int32 $.cntUsage; > has int32 $.th32ProcessID; > has Pointer $.th32DefaultHeapID; > has int32 $.th32ModuleID; > has int32 $.cntThreads; > has int32 $.th32ParentProcessID; > has long $.pcPriClassBase; > has int32 $.dwFlags; > HAS Str @.szExeFile[260] is CArray; # MAX_PATH on windows is 260 > }; > > > ... is there is a raku method that gives me the size of this data > structure? > > In C for example one would use sizeof() to provide the size. In raku I > could not find the documentation that would provide this information. > > Thanks, > Paul Procacci > -- > __ > > :(){ :|:& };: > -- __ :(){ :|:& };:
NativeCall -- size of data structure
Hey Gents, Hopefully a simple question that I could not find the answer to. Given the following: class PROCESSENTRY32 is repr('CStruct') { has int32 $.dwSize; has int32 $.cntUsage; has int32 $.th32ProcessID; has Pointer $.th32DefaultHeapID; has int32 $.th32ModuleID; has int32 $.cntThreads; has int32 $.th32ParentProcessID; has long $.pcPriClassBase; has int32 $.dwFlags; HAS Str @.szExeFile[260] is CArray; # MAX_PATH on windows is 260 }; ... is there is a raku method that gives me the size of this data structure? In C for example one would use sizeof() to provide the size. In raku I could not find the documentation that would provide this information. Thanks, Paul Procacci -- __ :(){ :|:& };:
Re: for and ^ question
On 1/1/21 10:47 PM, Patrick R. Michaud wrote: On Fri, Jan 01, 2021 at 05:41:04PM -0800, ToddAndMargo via perl6-users wrote: On 1/1/21 6:32 AM, David Santiago wrote: say $_ for {0.1+$_}...^5 Is there a way to do this without the finger wagging? say $_ for {0.1+$_}...^2 If you're going to a sequence operator ("...") instead of a range operator (".."), then you can specify the increment this way and it may be more readable: > say $_ for 0.1, 0.2 ...^ 2; Raku will auto-deduce the sequence from the values in the list on the LHS of the sequence operator: > say $_ for 0.6, 1.1 ...^ 10; This can be of course extended -- to count from $a up to $b in steps of $x, one can write: > say $_ for $a, $a+$x ...^ $b Note that in these examples the caret is part of the sequence operator, it's not a prefix to the $b argument. Pm Hi Patrick, Awesome explanation. I have added the following to my notes on "for" loops. Anyone want to see the whole "for" notes, let me know with a "ping Todd" on the subject line -T Looping using an rational (Rat, 0.45) and floating point (Num, 0.45e0) (also avoids having to use a C loop): Notes: it needs two points to know the iteration value and an end point. the tripple dots the ^ immediately after three third dot # loop from 0.0 to just before 2.0 by 0.3 > say $_ for 0.0, 0.3 ...^2.0; 0 0.3 0.6 0.9 1.2 1.5 1.8 # loop from 0.0e0 to just before 2.0e0 by 0.3e0 > say $_ for 0.0e0, 0.3e0 ...^2e0; 0 0.3 0.6 0.8999 # chuckle! 1.2 1.5 1.8 -- ~~ Computers are like air conditioners. They malfunction when you open windows ~~
Re: concurrency of asynchronous events - input from multiple keyboards
On Fri, Jan 01, 2021 at 03:20:09PM -0500, Vadim Belman wrote: > As it seems that Audio::PortMIDI lacks non-blocking interface, I think a > solution would be to read events in a dedicated thread and re-submit them > into a Supplier. Something like: > > my Supplier $midi-events; > > start { > loop { > my $ev = $midi.read; > $midi-events.emit: $ev; > } > } > > > $midi-events can then be used in your react block. BTW, I think calling > method 'poll' must not be needed because `read` should block until actual > event is available. At least this is how I understand the normal order of > things. Vadim, Thank you for your reply. I tried out not calling $midi.poll, but found that $midi.read would return undef events (rather than blocking until it received an event). So I added it back in. Thank you for the example of how to set up a supply. On Fri, Jan 01, 2021 at 02:51:57PM -0600, Brad Gilbert wrote: > I think the simplest way to turn that into a Supply is to use the `supply` > keyword > > my $pm = Audio::PortMIDI.new; > > > my $input = supply { > my $stream = $pm.open-input($input-device-number, 32); > > DONE { > $stream.close; > } > > loop { > emit $stream.read(1); > } > } > > > react { > whenever key-pressed(:!echo) { > given .fc { > when 'q' { done } > default { .raku.say } > } > } > > my $voice = $pm.open-output($output-device-number, 32); > whenever $input { > $voice.write(|$_); > } > } Brad, Thank you for your reply. I was able to get my code working thanks to the examples from you and Vadim. Here is what I ended up with: my $pm = Audio::PortMIDI.new; # Set up supply to read MIDI events. my $input = supply { my $stream = $pm.open-input($input-device-number, 32); LAST { $stream.close; } loop { emit $stream.read(1) if $stream.poll; } } # Set up handle to send MIDI events to the synthesizer. my $voice = $pm.open-output($output-device-number, 32); react { # Read key presses from the computer keyboard. # TODO: change $voice as needed based on computer keyboard input. whenever key-pressed(:!echo) { given .fc { when 'q' { done } default { .raku.say } } } # Read MIDI events and send to the synthesizer. whenever $input { $voice.write(|$_); } } -kolibrie signature.asc Description: PGP signature