azaragoza has asked for the wisdom of the Perl Monks concerning the following question:

I'm new to perl and I've been trying to code GlobalMemoryStatusEx in a perl script but I haven't had any luck, any help would be appreciated, here is my code
use warnings; use Win32::API; use Win32::API::Struct; use Data::Dumper; use strict; Win32::API::Struct->typedef(MEMORYSTATUSEX { DWORD dwLength; DWORD dwMemoryLoad; DWORDLONG ullTotalPhys; DWORDLONG ullAvailPhys; DWORDLONG ullTotalPageFile; DWORDLONG ullAvailPageFile; DWORDLONG ullTotalVirtual; DWORDLONG ullAvailVirtual; DWORDLONG ullAvailExtendedVirtual; }); Win32::API->Import( 'kernel32', 'VOID GlobalMemoryStatusEx(LPMEMORYSTATUSEX lpBuffer); + my $stat = Win32::API::Struct->new('MEMORYSTATUSEX', lpBuffer); GlobalMemoryStatusEx($stat); my $dwLength = FormatBytes( $stat->{dwLength} ); print "Size of memory status structure: $dwLength\n"; $dwTotalPhys = FormatBytes( $stat->{ullTotalPhys} ); print "Total Available physical memory --> ullTotalPhys\n\n"; printf "Memory in use: %ld%%\n", $stat->{dwMemoryLoad}; my $dwTotalPhys = FormatBytes( $stat->{dwTotalPhys} ); print "Total physical memory --> $dwTotalPhys\n"; my $dwAvailPhys = FormatBytes( $stat->{ullAvailPhys} ); print "Free physical memory ---> ullAvailPhys \n"; my $dwTotalVirtual = FormatBytes( $stat->{ullTotalVirtual} ); print "Total virtual memory ---> $ullTotalVirtual \n"; my $dwAvailVirtual = FormatBytes( $stat->{ullAvailVirtual} ); print "Free virtual memory ----> $ullAvailVirtual\n"; my $dwTotalPageFile = FormatBytes( $stat->{ullTotalPageFile} ); print "Total paging file ------> $ullTotalPageFile\n"; my $dwAvailPageFile = FormatBytes( $stat->{ullAvailPageFile} ); print "Free paging file -------> $ullAvailPageFile\n\n";
Thanks for any help.

Replies are listed 'Best First'.
Re: How do I code GlobalMemoryStatusEx in perl
by almut (Canon) on Mar 11, 2009 at 18:09 UTC
    Win32::API::Struct->typedef(MEMORYSTATUSEX { DWORD dwLength; ...

    For one, you probably want some Perl-compatible syntax :)

    Win32::API::Struct->typedef(MEMORYSTATUSEX => qw{ DWORD dwLength; ... });

    From the docs:

    typedef NAME, TYPE, MEMBER, TYPE, MEMBER, ...

    This method defines a structure named NAME. The definition consists of types and member names, just like in C. In fact, most of the times you can cut the C definition for a structure and paste it verbatim to your script, enclosing it in a qw() block. The function takes care of removing the semicolon after the member name.
      Thanks for all the help because of the help I was able to code the perl script, but it does not return any values. Does anyone now why?
      use warnings; use Win32::API; use Win32::API::Struct; use Data::Dumper; use Win32::SystemInfo; use strict; typedef Win32::API::Struct MEMORYSTATUSEX => qw{ DWORD dwLength; DWORD dwMemoryLoad; DWORDLONG ullTotalPhys; DWORDLONG ullAvailPhys; DWORDLONG ullTotalPageFile; DWORDLONG ullAvailPageFile; DWORDLONG ullTotalVirtual; DWORDLONG ullAvailVirtual; DWORDLONG ullAvailExtendedVirtual; }; Win32::API->Import( 'kernel32', 'BOOL GlobalMemoryStatusEx( LPMEMORYSTATUSEX lpBuffer +)' ); my $stat = Win32::API::Struct->new( 'MEMORYSTATUSEX' ); GlobalMemoryStatusEx($stat); my $dwLength = FormatBytes( $stat->{dwLength} ); print "\nSize of memory status structure: $dwLength\n"; my $ullTotalPhys = FormatBytes( $stat->{ullTotalPhys} ); print "Total Available physical memory --> $ullTotalPhys\n\n"; printf "Memory in use: %ld%%\n", $stat->{dwMemoryLoad}; my $ullAvailPhys = FormatBytes( $stat->{ullAvailPhys} ); print "Free physical memory ---> $ullAvailPhys \n"; my $ullTotalVirtual = FormatBytes( $stat->{ullTotalVirtual} ); print "Total virtual memory ---> $ullTotalVirtual \n"; my $ullAvailVirtual = FormatBytes( $stat->{ullAvailVirtual} ); print "Free virtual memory ----> $ullAvailVirtual\n"; my $ullTotalPageFile = FormatBytes( $stat->{ullTotalPageFile} ); print "Total paging file ------> $ullTotalPageFile\n"; my $ullAvailPageFile = FormatBytes( $stat->{ullAvailPageFile} ); print "Free paging file -------> $ullAvailPageFile\n\n"; #--------------------------------------------------------------------- +------ # sub FormatBytes { my( $Number ) = @_; my( $Suffix ) = ""; my $K = 1024; my $M = 1024 * $K; my $G = 1024 * $M; if( $G <= $Number ) { $Suffix = "(G)"; $Number /= $G; } elsif( $M <= $Number ) { $Suffix = "(M)"; $Number /= $M; } elsif( $K <= $Number ) { $Suffix = "(K)"; $Number /= $K; } $Number =~ s/(\.\d{0,2})\d*$/$1/; {} while ($Number =~ s/^(-?\d+)(\d{3})/$1,$2/); return( $Number . $Suffix ); } #--------------------------------------------------------------------- +------
      As I looked for answers in the web I found a lot of questions on how to do this with perl, unfortunately I have not been successful.
Re: How do I code GlobalMemoryStatusEx in perl
by syphilis (Archbishop) on Mar 12, 2009 at 01:29 UTC
    Hi azaragoza,
    Here's an Inline::C solution:
    use warnings; use Inline C => Config => BUILD_NOISY => 1; use Inline C => <<'EOC'; #define _WIN32_WINNT 0x0500 #include <windows.h> #define DIV 1024 char *divisor = "K"; #define WIDTH 7 void foo() { MEMORYSTATUSEX statex; statex.dwLength = sizeof (statex); GlobalMemoryStatusEx (&statex); printf ("%ld percent of memory is in use.\n", statex.dwMemoryLoad); printf ("There are %*I64d total %sbytes of physical memory.\n", WIDTH, statex.ullTotalPhys/DIV, divisor); printf ("There are %*I64d free %sbytes of physical memory.\n", WIDTH, statex.ullAvailPhys/DIV, divisor); printf ("There are %*I64d total %sbytes of paging file.\n", WIDTH, statex.ullTotalPageFile/DIV, divisor); printf ("There are %*I64d free %sbytes of paging file.\n", WIDTH, statex.ullAvailPageFile/DIV, divisor); printf ("There are %*I64d total %sbytes of virtual memory.\n", WIDTH, statex.ullTotalVirtual/DIV, divisor); printf ("There are %*I64d free %sbytes of virtual memory.\n", WIDTH, statex.ullAvailVirtual/DIV, divisor); // Show the amount of extended memory available. printf ("There are %*I64x free %sbytes of extended memory.\n", WIDTH, statex.ullAvailExtendedVirtual/DIV, divisor); } void bar() { Inline_Stack_Vars; MEMORYSTATUSEX statex; char buffer [30]; statex.dwLength = sizeof (statex); GlobalMemoryStatusEx (&statex); Inline_Stack_Reset; Inline_Stack_Push(sv_2mortal(newSVuv(statex.dwMemoryLoad))); _ui64toa(statex.ullTotalPhys/DIV, buffer, 10); Inline_Stack_Push(sv_2mortal(newSVpv(buffer, 0))); _ui64toa(statex.ullAvailPhys/DIV, buffer, 10); Inline_Stack_Push(sv_2mortal(newSVpv(buffer, 0))); _ui64toa(statex.ullTotalPageFile/DIV, buffer, 10); Inline_Stack_Push(sv_2mortal(newSVpv(buffer, 0))); _ui64toa(statex.ullAvailPageFile/DIV, buffer, 10); Inline_Stack_Push(sv_2mortal(newSVpv(buffer, 0))); _ui64toa(statex.ullTotalVirtual/DIV, buffer, 10); Inline_Stack_Push(sv_2mortal(newSVpv(buffer, 0))); _ui64toa(statex.ullAvailVirtual/DIV, buffer, 10); Inline_Stack_Push(sv_2mortal(newSVpv(buffer, 0))); _ui64toa(statex.ullAvailExtendedVirtual/DIV, buffer, 10); Inline_Stack_Push(sv_2mortal(newSVpv(buffer, 0))); Inline_Stack_Done; Inline_Stack_Return(8); } EOC foo(); @info = bar(); print "\n"; print "$_\n" for @info;
    The foo function simply prints the values to stdout.
    The bar function returns the same values to an array.

    Unfortunately, it works only with Microsoft compilers, but not MinGW. I don't know why GlobalMemoryStatusEx is inaccessible to MinGW - working out why should help fill in my day :-)

    Cheers,
    Rob
      Unfortunately, it works only with Microsoft compilers, but not MinGW

      I think the problem with MinGW is that _WIN32_WINNT does not get defined to 0x0500 early enough. A solution is to insert the following code into the script (just above the foo function):
      #ifndef _MSC_VER typedef struct _MEMORYSTATUSEX { DWORD dwLength; DWORD dwMemoryLoad; DWORDLONG ullTotalPhys; DWORDLONG ullAvailPhys; DWORDLONG ullTotalPageFile; DWORDLONG ullAvailPageFile; DWORDLONG ullTotalVirtual; DWORDLONG ullAvailVirtual; DWORDLONG ullAvailExtendedVirtual; } MEMORYSTATUSEX,*LPMEMORYSTATUSEX; WINBASEAPI BOOL WINAPI GlobalMemoryStatusEx(LPMEMORYSTATUSEX); #endif
      Works for me, anyway :-)

      Cheers,
      Rob
      Thanks Rob I'll try an find a C compiler and use this until I can get the perl script working.
        I'll try an find a C compiler

        If you're using ActivePerl:
        ppm install MinGW
        Cheers,
        Rob