Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.
 
PerlMonks  

Win32::API - How to call an Imported function with Win32::API::Types ?

by fx (Pilgrim)
on Jul 01, 2004 at 15:04 UTC ( [id://371110] : perlquestion . print w/replies, xml ) Need Help??

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

I am trying to call a function within a DLL using Win32::API and am trying to do using Import and prototypes.

The parameters required by the function are all custom types, and so after reading the C header files and Win32::API::Type I have defined these types and Imported the function:

use strict; use Win32::API; Win32::API::Type->typedef( 'OMDTEXTZ', 'TCHAR'); Win32::API::Type->typedef( 'OMDERROR', 'ULONG'); Win32::API::Type->typedef( 'OMD32U', 'ULONG' ); Win32::API::Type->typedef( 'OMDCLIENT', 'ULONG' ); Win32::API->Import( 'omdapi', 'OMDERROR OMDClientCreate ( OMDTEXTZ* pUsername, OMDTEXTZ* pPassword, OMDTEXTZ* pDomain, OMD32U options, OMDCLIENT* pClient )' ); ## my $return = OMDClientCreate( "OMG, I am so confused!" );

My question is: how am I supposed to call OMDClientCreate? When the C function wants a OMDTEXTZ* do I simply give it a Perl string? What about when it wants a OMDCLIENT* to return me the client handle?

I have found little to no documention in either Win32::API or Win32::API::Type to explain how this is done.

Thanks,

fx, Infinity is Colourless

  • Comment on Win32::API - How to call an Imported function with Win32::API::Types ?
  • Download Code

Replies are listed 'Best First'.
Re: Win32::API - How to call an Imported function with Win32::API::Types ?
by BrowserUk (Patriarch) on Jul 01, 2004 at 18:03 UTC

    Yes. Just pass perl variables (NOT constants!) for each of the parameters.

    ... my $uname = 'USER1'; my $passw = 'PASS'; my $domain = 'DOMAIN'; ## use constant NICE_OPT_NAME => 128; etc. if you want symblic names my $options = 128 | 16 | 2; my $client; OMDClinetCreate( $uname, $passw, $domain, $options, $client ) or die $^E; ## Add this to your other calls also!.

    The whole reason for using teh typedefs is that it allows the module to do the required conversion work for you.


    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "Think for yourself!" - Abigail
    "Memory, processor, disk in that order on the hardware side. Algorithm, algoritm, algorithm on the code side." - tachyon

      I still can't get it to work with Import. As you suggest, I have tried:

      use strict; use Win32::API; Win32::API::Type->typedef( 'OMDTEXTZ', 'TCHAR'); Win32::API::Type->typedef( 'OMDERROR', 'ULONG'); Win32::API::Type->typedef( 'OMD32U', 'ULONG' ); Win32::API::Type->typedef( 'OMDCLIENT', 'ULONG' ); Win32::API->Import( 'omdapi', 'OMDERROR OMDClientCreate ( OMDTEXTZ* pUsername, OMDTEXTZ* pPassword, OMDTEXTZ* pDomain, OMD32U options, OMDCLIENT* pClient )' ); my $username = 'user1'; my $password = 'pass1'; my $domain = 'domain1'; my $options = 0; my $client; my $return = OMDClientCreate( $username, $password, $domain, $options, + $client ) or die $^E;

      And although the call to OMDClientCreate does not die, it also puts nothing into the $client variable.

      However, if I try it using a parameter list instead:

      use strict; use Win32::API; my $function = Win32::API->new( 'omdapi', 'OMDClientCreate', 'PPPIP', +'I'); my $client = pack('L', 0); my $username = 'user1'; my $password = 'pass1;; my $domain = 'domain1'; my $return = $function->Call( $username, $password, $domain, 0, $clien +t );

      it actually works (which I have confirmed by using Data::Dumper on the $client variable).

      Am I missing something?

      Thanks,

      fx, Infinity is Colourless

        I suspect that the problem is that TCHAR is not a type that Win32::API::Type knows about. You can find the list of those that it does know about at the bottom of the Type.pm source file.

        You probably need to change

        Win32::API::Type->typedef( 'OMDTEXTZ', 'TCHAR');

        to something like

        Win32::API::Type->typedef( 'OMDTEXTZ', 'unsigned char') or die $^E;

        However, if you were to add some error checking to your calls (as above and in my original snippet. E.g. ...or die $^E;), then the module would be telling you what is wrong and where.


        Examine what is said, not who speaks.
        "Efficiency is intelligent laziness." -David Dunham
        "Think for yourself!" - Abigail
        "Memory, processor, disk in that order on the hardware side. Algorithm, algoritm, algorithm on the code side." - tachyon
Re: Win32::API - How to call an Imported function with Win32::API::Types ?
by vladdrak (Monk) on Jul 02, 2004 at 02:35 UTC
    This may not be of great help, but I've always used Win32::API a bit differently, (not importing) which worked for me. You're out there in no mans land with Win32::API for the most part, doc/example-wise, so I hope you have some C under you belt. Try packing up your stuff proper, minus the typedefs, and just shove it in there.

    Warning: you may have to sacrifice livestock or perform some strange ritual in a musty basement in order to get everything working.

    -vlad
    my $FileTimeToSystemTime = new Win32::API('Kernel32.dll', 'FileTimeToS +ystemTime',['P','P'],'I'); sub FileTimeToSystemTime { my $filetime=shift; my $systemtime="\0" x (2*8); $FileTimeToSystemTime->Call($filetime, $systemtime) or return; return unpack( 'S8', $systemtime); }
Re: Win32::API - How to call an Imported function with Win32::API::Types ?
by chinman (Monk) on Jul 02, 2004 at 13:14 UTC