Reinhard Pagitsch <[EMAIL PROTECTED]> writes:
>>
>Thank you for the informations. I think I was not clear enough.
>e.g: I have the XS function:
>void add_counter(ObjectName, CounterName, InstanceName, pQwy, pError)
>(I found it in the module Win32::PerfMon)
>
>This function uses PdhAddCounter() to create a new handle to a counter. 
>The first four
>parrameters to the function are clear. Then there is the parameter 
>pError which holds an
>error message if PdhAddCounter() returns an error. PdhAddcounter also 
>return the handle to
>the created counter in the 4th parameter of this function:
>stat = PdhAddCounter(hQwy, (LPTSTR)str, dwGlen, &cnt);
>But I can not understand how the .pm get this handle  back??????

Because the XS function should assign to the SV that perl passed
like perl code:

sub add_counter
{
  #             0             1              2      3
  my ($ObjectName, $CounterName, $InstanceName, $pQwy) = @_;
  ...
  $_[4] = $error; 
}

Your code below is doing that via 
 sv_setpvn(perror,...) 

But you are setting it to nonsense.

>This is the line in the .pm where the handle will be stored:
>my $NewCounter = add_counter($ObjectName, $CounterName, $InstanceName, 
>$self->{'HQUERY'}, $self->{'ERRORMSG'});
>

So in this case $self->{ERRORMSG} gets set.

>>
>Here is the code. I am sure that there many not needed things in it.
>(What I want to do is that the return of this function is 0 on success, 
>1 on error, the error message in the parameter perror if one
>and the result in pr like this:
>int ListProcesses(pr,perror)
>And now I want to know how to do this so that I can call the XS like this:
>my $status = ListProcesses(%result, $error);
>(or similar)
>)
>--------------------- code---------------------
>SV *
>ListProcesses(pr,perror)
>    SV* pr
>    SV* perror
>    PREINIT:
>        AV * result;
>        DWORD aProcesses[1024];
>        DWORD cbNeeded;
>        DWORD cProcesses;
>            unsigned int i;
>            char szProcessName[MAX_PATH] = "unknown";
>            DWORD err;
>            HMODULE hMod;
>        char tmp[1024];
>        HV * rh;
>
>    CODE:
>        SetLastError(0);
>        result = (AV *)sv_2mortal((SV *)newAV());
>        rh = (HV *)sv_2mortal((SV *)newHV());
>    if(!EnumProcesses(aProcesses,sizeof(aProcesses),&cbNeeded))
>    {
>        err = GetLastError();
>        sv_setpvn(perror, "EnumProcesses: An error occured ", err);
>        XPUSHs(sv_2mortal(newSViv(-1)));
>    }
>    cProcesses = cbNeeded / sizeof(DWORD);
>    for ( i = 0; i < cProcesses; i++ ) {
>         HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION 
>|PROCESS_VM_READ,FALSE, aProcesses[i] );
>         if(NULL != hProcess)
>         {
>             if ( EnumProcessModules( hProcess, &hMod, sizeof(hMod), 
>&cbNeeded) > 0 )
>        {
>                GetModuleBaseName( hProcess, hMod, szProcessName, 
>sizeof(szProcessName) );
>                
>hv_store(rh,szProcessName,strlen(szProcessName),newSVnv(aProcesses[i]), 0);
>            } else {
>                if(strcmp(szProcessName, "unknown")) {
>                err = GetLastError();

Which looks windows-ish.
If I recall correctly there is a function FormatMessage() 
which returns error message as a string.
See perl/win32/win32.c and win32_strerror().

>                if(err == ERROR_PARTIAL_COPY) {
>                    printf("ERROR_PARTIAL_COPY\n");
>                }
>                printf("EnumProcessModules: An error occured %i Process: 
>(%s) PID: %i\n", err,szProcessName, aProcesses[i]);
>                sv_setpvn(perror, "An error occured ", err);

setpvn sets PV (string) part to char * and len.
Passing err (error number) as length makes no sense.
You are probably trying to return a dual value string/number.
That is a tad tricky - you do something like this: 
                 sv_upgrade(perror,SVt_PVIV);    // has PV and IV
                 sv_setpv(perror,"Some String"); // string
                 sv_setiv(perror,(IV) err);      // IV
                 SvPOK_on(perror);               // But string valid too 

>                XPUSHs(sv_2mortal(newSViv(-1)));

It is traditional to return undef for errors.

>            }
>        }
>
>         } else {
>            err = GetLastError();
>            sv_setpvn(perror, "Can not open Process ", err);
>            XPUSHs(sv_2mortal(newSViv(-1)));
>        }
>        }
>        av_push(result, newRV((SV *)rh));
>        RETVAL = newRV((SV *)result);
>    OUTPUT:
>       RETVAL
>
>
>>>(I plan to upload it to CPAN)
>>>
>>>mit freundlichen GrÃÃen,
>>>with my best regards,
>>>Reinhard
>>
>>  
>>
>
>
>Thank you,
>Reinhard

Reply via email to