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
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.
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, $client );
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.
According to the source, TCHAR is a valid type which is why I chose it. Hmm...
As you suggest, I shall put lots of error checking in and see what isn't being liked.
Thanks,
fx, Infinity is Colourless
Ok, I've just added ...or die $^E to every Win32::API module call and nothing is die'ing. As far as I can see the call to the function inside the DLL is actually working
Hmm...
fx, Infinity is Colourless
Try initializing my $client = pack('L', 0); as you did in the code that worked.
my $FileTimeToSystemTime = new Win32::API('Kernel32.dll', 'FileTimeToSystemTime',['P','P'],'I');
sub FileTimeToSystemTime {
my $filetime=shift;
my $systemtime="\0" x (2*8);
$FileTimeToSystemTime->Call($filetime, $systemtime) or return;
return unpack( 'S8', $systemtime);
}
I'm not sure if this would help in your case, but I have successfully used Dave Roth's Win32::API::Prototype when making Win32 API calls. It just makes it a bit easier.
chinmanperlmonks.org content © perlmonks.org and BrowserUk, chinman, fx, vladdrak
prlmnks.org © 2006 edmund von der burg (eccles & toad)
v 0.03