http://qs321.pair.com?node_id=359642

Here is an outline of how to make Win32::API much easier to use. It results in code like:

use Win32::API qw( CreateIoCompletionPort N kernel32 N N N N ); use Win32::API qw( ... ); # ... my $hIOCP= CreateIoCompletionPort( $hSocket, 0, 0, 0 ); # ...

which is much nicer than how I've used Win32::API. Of course, support for more DWIM argument types is also in order, but I think I've seen such work underway elsewhere. (In fact, I'd probably allow for a code ref as an argument specification...)

Here is how simple this improvement is to implement:

sub Win32::API::import { my( $class, $sub, $ret, $lib, @args )= @_; my( $pkg )= (caller 1)[3]; my $obj = $class->new( $lib, $sub, [@args], $ret ) or croak( "Can't find $sub in $lib" ); no strict 'refs'; *{"$pkg::$sub"} = sub { $obj->Call( @_ ); }; }

Does this type of simplification come from thinking like "the users", or am I just strange? Does this seem like a huge improvement to others? Anyone else felt "from the beginning" that Win32::API should be creating code refs, like that was the "natural" interface to provide?

I often suspect that many code authors don't put much stress on the point of view of the users of their code. But I find that my view of the world (in so many respects) looks quite skewed to most people...

I'm sorry that this is such a skimpy node. I'm tied up with my day job but wanted to throw this idea out anyway...

- tye        

Replies are listed 'Best First'.
Re: How to make Win32::API easy to use
by BrowserUk (Patriarch) on Jun 02, 2004 at 19:42 UTC

    I think that Win32::API::Prototype makes it easier than the Win32::API.

    use Win32::API::Prototype; ApiLink( 'Kernel32', q[ HANDLE CreateIoCompletionPort( HANDLE FileHandle, HANDLE ExistingCompletionPort, ULONG_PTR CompletionKey, DWORD NumberOfConcurrentThreads )] ); my $hIOCP = CreateIoCompletionPort( $hSocket, 0, 0, 0 );

    Maybe a combination of that and your import function would simplify it further?


    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "Think for yourself!" - Abigail

      I'd look at Win32::API::Prototype but it doesn't appear to be on CPAN (to which your link points). Google says it is a Roth module. I tend to avoid non-CPAN modules for a lot of reasons...

      Ahh, nice, this one includes source code and it is all in Perl (which means the usual reason Roth gives for not putting on CPAN shouldn't apply; maybe that will happen). It appears to do quite simple translation from typedef'd types to Win32::API types, which isn't at all what I was thinking it would do (I find that this step is usually the easiest step).

      So the two methods could probably be merged rather easily.

      - tye        

        It is on CPAN: here. Hopefully that link will take you direct to the source. It does me. The other link was from the search.cpan.org page, amd it doesn't link, though other links from the same entry do?

        It does also export the entrypoint name into the calling code as yours would.


        Examine what is said, not who speaks.
        "Efficiency is intelligent laziness." -David Dunham
        "Think for yourself!" - Abigail
Re: How to make Win32::API easy to use
by demerphq (Chancellor) on Jun 02, 2004 at 20:33 UTC

    Does this type of simplification come from thinking like "the users", or am I just strange? Does this seem like a huge improvement to others? Anyone else felt "from the beginning" that Win32::API should be creating code refs, like that was the "natural" interface to provide?

    I totally agree. A similar example for me is this from DBI:

    $rc = $sth->bind_col($col_num, \$col_variable); $rc = $sth->bind_columns(@list_of_refs_to_vars_to_bind);

    Ive never understood why that isnt:

    $rc = $sth->bind_col($col_num, $col_variable); $rc = $sth->bind_columns(@list_to_bind);
    As inside it could easily be:
    my ($col_num)=@_; my $col_variable=\$_[1];
    or
    my @refs=map { \$_ } @_;

    ---
    demerphq

      First they ignore you, then they laugh at you, then they fight you, then you win.
      -- Gandhi


      This hits on a difference in our "Perl views" (like "world views") that has come up before. I find aliases in Perl to be a special case and so I prefer to avoid them except in certain situations.

      I guess my heuristic is to avoid using them except across very short distances. The distance between the call to bind() and the definition of sub bind is pretty big, if you look at it one way.

      However, Perl's read sets a precedent that I sometimes follow and this case is close enough that I could certainly make arguments that it would an appropriate use here. But I also see two reason why someone wouldn't do this. The first is avoiding user surprise as I tried to explain briefly above (and probably failed).

      To make it more concrete, we don't have (w/o using C code not built into Perl) the ability to do:

      my( $name, $dob, $salary ); my @arrayOfAliases= ...( $name, $dob, $salary ); ...->bind_columns( @arrayOfAlises ); # nor my( $name, $dob, $salary ); my %colMap= ( Name => aliasOf($name), DOB => aliasOf($dob), Salary => aliasOf($salary), ); ...->bind_columns( @colMap{@colNames} ); # nor ...->bind_columns( map ... );

      so using aliases in your API restricts how people can use your API. (And I don't think my last example could be used even if you allow for a module including C code.)

      The second reason is "comfort" of implementation, which I see fits exactly the "not thinking of your users" problem I brought up.

      In Perl4 we had globs. In Perl5 we got references. In Perl6 we'll finally get full control over aliases and so they'll finally be acceptable to me to use in more general ways (I suspect).

      - tye        

Re: How to make Win32::API easy to use
by dragonchild (Archbishop) on Jun 02, 2004 at 18:47 UTC
    Yes Yes YES! As an utterly unrelated sidenote, this would also make events in PerlScript much easier to use. :-)

    ------
    We are the carpenters and bricklayers of the Information Age.

    Then there are Damian modules.... *sigh* ... that's not about being less-lazy -- that's about being on some really good drugs -- you know, there is no spoon. - flyingmoose

    I shouldn't have to say this, but any code, unless otherwise stated, is untested

just alias import to Import
by PodMaster (Abbot) on Jun 03, 2004 at 00:05 UTC
    I often write
    use Win32::API; Win32::API::->Import("kernel32","HANDLE GetCurrentProcess()");
    so it seems to me that all that is required is a
    { no strict 'refs'; *import = \&Import; }
    . That and maybe eliminating the eval from Win32::API::Import.

    MJD says "you can't just make shit up and expect the computer to know what you mean, retardo!"
    I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README).
    ** The third rule of perl club is a statement of fact: pod is sexy.

Re: How to make Win32::API easy to use
by enoch (Chaplain) on Jun 02, 2004 at 20:42 UTC
    There just aren't enough ++'s in the world for that...