Todd, I've made a mistake. Raku does ensure a pointer gets passed to the function transparently when referencing a structure and doesn't require one to be explicit. I stand corrected.
~Paul On Sun, Jan 3, 2021 at 1:40 PM Paul Procacci <pproca...@gmail.com> wrote: > Todd, > > Nothing you stated addresses my initial question nor subsequent findings. > My question is simply how to retrieve the value that gets stored in the > CArray; nothing more. > My subsequent findings included the following as I believe I'm running > into it: https://github.com/rakudo/rakudo/issues/3633 > > > Irrelevant musings: > -- > A windows handle is a pointer. > A handle is an abstraction to a memory location that can be used in > subsequent api calls. > Declaring it as any incarnation of an int is a mistake and will not > function properly across all machines. > > -- > The windows api requires the PROCESSENTRY32 structure member dwSize to be > set to size of the structure. > There's nothing wrong with my instantiation. > Passing this structure to Process32First and Process32Next in the manner I > have done so works. > > Furthermore you can't pass a naked $entry to like so: > Process32First($handle, $entry) > It has to be a pointer; had you tried what you suggested, raku would have > thrown errors and for good reason. > > -- > My suggestion is to try it yourself. Utilize the windows api in a manner > in which you'd expect it to run > properly and see what happens. Retrieve the value in szExeFile. If you'd > get it to work properly, show me > what version of raku you are using and supply it as it could be a bug in > the version I'm running. > > ~Paul > > On Sun, Jan 3, 2021 at 5:37 AM ToddAndMargo via perl6-users < > perl6-us...@perl.org> wrote: > >> On 1/2/21 11:38 PM, Paul Procacci wrote: >> > 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-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-process32first >> > >> > >> https://docs.microsoft.com/en-us/windows/win32/api/tlhelp32/nf-tlhelp32-process32next >> > < >> 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 >> >> Hi Paul, >> >> Please bottom post. It removes a lot of confusion. >> >> ~~~~~~~~~~~~~~~~~~~~~~ >> CreateToolhelp32Snapshot: >> >> C++ >> >> HANDLE CreateToolhelp32Snapshot( >> DWORD dwFlags, >> DWORD th32ProcessID >> ); >> >> >> The return is a "handle", not a pointer. >> >> You declare it as such: >> >> sub CreateToolhelp32Snapshot(int32, int32 --> Pointer) is >> native('Kernel32') { * }; >> >> my $ptr = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); >> >> >> I am not sure you are declaring that correctly. >> >> I would declare it: >> sub CreateToolhelp32Snapshot(int32, int32 --> int32) is >> native('Kernel32') { * }; >> >> my $handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) >> >> >> ~~~~~~~~~~~~~~~~~~~~~~ >> >> Process32First: >> >> C++ >> >> BOOL Process32First( >> HANDLE hSnapshot, >> LPPROCESSENTRY32 lppe >> ); >> >> Returns a True or False for success/failure. >> >> You give it the "handle" you got from >> CreateToolhelp32Snapshot >> >> lppe is actually a C Pointer point to a c++ >> structure called PROCESSENTRY32 >> >> C++ >> >> typedef struct tagPROCESSENTRY32 { >> DWORD dwSize; >> DWORD cntUsage; >> DWORD th32ProcessID; >> ULONG_PTR th32DefaultHeapID; >> DWORD th32ModuleID; >> DWORD cntThreads; >> DWORD th32ParentProcessID; >> LONG pcPriClassBase; >> DWORD dwFlags; >> CHAR szExeFile[MAX_PATH]; >> } PROCESSENTRY32; >> >> You are duplicating this structure with >> >> 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; >> }; >> >> And calling it with: >> >> my PROCESSENTRY32 $entry .= >> new(:dwSize(nativesizeof(PROCESSENTRY32))); >> >> Process32First($ptr, nativecast(Pointer, $entry)); >> >> I would tend to do it this way: >> >> my $entry = PROCESSENTRY32,new(); >> sub Process32First( int32, PROCESSENTRY32 is rw --> Bool ); >> my Bool $PassFail = Process32First( $handle, $entry) >> >> >> lppe, on the other hard is a pointer. Adding "is rw" will >> read the structure it points to into your object. >> >> >> ~~~~~~~~~~~~~~~~~~~~~~ >> >> Process32Next: >> >> C++ >> >> BOOL Process32Next( >> HANDLE hSnapshot, >> LPPROCESSENTRY32 lppe >> ); >> >> sub Process32Next( int32, PROCESSENTRY32 is rw --> Bool ); >> >> while Process32Next( handle, $entry ) { >> say $entry.szExeFile[0].ord; >> say $entry.szExeFile[1].ord; >> } >> >> ~~~~~~~~~~~~~~~~~~~~~~ >> >> By the way, the uint16 size is going to be a "little ending". >> >> 0xF5D3 comes out [0]=0xD3 and [1] 0xF4 >> >> Native call will not convert it for you if you addess it as >> a CArray. >> >> I have a conversion for that too. >> >> >> HTH, >> -T >> >> >> > > -- > __________________ > > :(){ :|:& };: > -- __________________ :(){ :|:& };: