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

Hello monks.

I'm having an odd problem with Win32::API, but I don't believe it's a bug in the module, but rather something that I've missed.

The problem is that the code below runs fine by itself, but when I put it in a module which I use from my main script I get the following error:

Win32::API::parse_prototype: WARNING unknown output parameter type 'BO +OL' at C:/Perl/site/lib/Win32/API.pm line 273.
It seems to me that the problem might be related to namespacing or perhaps some obscure scoping rule - please enlighten me as to what I've overlooked here. I've tried changing the return type to INT and BYTE with the same result.
use strict; use warnings; use Win32::API; Win32::API::Struct->typedef(SYSTEM_POWER_STATUS => qw ( BYTE ACLineStatus; BYTE BatteryFlag; BYTE BatteryLifePercent; BYTE Reserved1; DWORD BatteryLifeTime; DWORD BatteryFullLifeTime; )); my $bar = Win32::API->new('kernel32','BOOL GetSystemPowerStatus(SYSTEM +_POWER_STATUS status)'); my $foo = Win32::API::Struct->new('SYSTEM_POWER_STATUS'); $bar->Call($foo); foreach (qw( ACLineStatus BatteryFlag BatteryLifePercent Reserved1 + BatteryLifeTime BatteryFullLifeTime)) { print "$_: $foo->{$_}\n"; } }
Updated
I don't blame you for not replying yet - I can't reproduce the error if I write a module with the posted code from scratch, so something else must be going on in my script...

Another update Okay, I found a way to make it work/not work.
It turns out that for the package to work, the datastructure as well as the function (basically all the code I posted) needs to be written inside the function that I call in the package...I'd like to know why this is the case, though :-p

Replies are listed 'Best First'.
Re: Win32::API missing types
by syphilis (Archbishop) on Oct 31, 2006 at 11:02 UTC
    Nemurenai,
    There's a fairly simple demonstration of your point that can be taken from the Win32::API docs - one that doesn't need a laptop to test out.
    Save the following file as 'mymod.pm':
    package mymod; use warnings; use Win32::API; #### define the structure Win32::API::Struct->typedef( POINT => qw{ LONG x; LONG y; }); #### import an API that uses this structure Win32::API->Import('user32', 'BOOL GetCursorPos(LPPOINT lpPoint)'); #### create a 'POINT' object my $pt = Win32::API::Struct->new('POINT'); #### call the function passing our structure object GetCursorPos($pt); #### and now, access its members print "The cursor is at: $pt->{x}, $pt->{y}\n"; 1;
    When you run that file as 'perl mymod.pm' you get output like the following (depending upon just where the cursor is located):
    D:\pscrpt>perl mymod.pm The cursor is at: 584, 1017 D:\pscrpt>perl mymod.pm The cursor is at: 213, 542
    Next, try running the following script (named 'test.pl'):
    use warnings; use mymod;
    That consistently produces the following output for me (with an accompanying segfault):
    D:\pscrpt>perl test.pl Win32::API::parse_prototype: WARNING unknown output parameter type 'BO +OL' at D:/ perl58_M/site/5.8.8/lib/Win32/API.pm line 273. Use of uninitialized value in concatenation (.) or string at mymod.pm +line 21. Use of uninitialized value in concatenation (.) or string at mymod.pm +line 21. The cursor is at: ,
    I can't offer a useful explanation of this ... but I guess it has something to do with the quirky way that Win32::API::Struct goes about doing whatever it is that Win32::API::Struct does.

    I don't think that Win32::API::Struct enables you to do anything that can't be done by using simply Win32::API.
    Win32::API::Struct merely simplifies the coding that's necessary. So you should be able to rewrite your code (using only Win32::API) in such a way that avoids the odd behaviour you've noted.

    Cheers,
    Rob
Re: Win32::API missing types
by Anonymous Monk on Oct 31, 2006 at 02:38 UTC
    It turns out that for the package to work, the datastructure as well as the function (basically all the code I posted) needs to be written inside the function that I call in the package...I'd like to know why this is the case, though :-p
    Its probably because you haven't shown your code :)