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
>>
>>
>>
>
> --
> __________________
>
> :(){ :|:& };:
>


-- 
__________________

:(){ :|:& };:

Reply via email to