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