HELP! Invoking a DLL function using Win32::API 
Author Message
 HELP! Invoking a DLL function using Win32::API

[posted and mailed]

Quote:



> > > I need to make use of a function from within a (3rd party) dll.
> > > I will be calling this function using perl. The function takes
> > > the following form:
> > > FUNCTION EX_GETCURRENCY
> > >    (P : POINTER; PSIZE : LONGINT; CURR  : SMALLINT) : SMALLINT;
> > > P is a pointer to a record, described below
> > [snip]
> > > * This is the structure of the record mentioned above
> > > TBatchCurrRec = Record
> > >   Name        : String[11];           { Currency name }
> > >     ScreenSymb  : String[3];            { Screen Symbol }
> > >     PrinterSymb : String[3];            { Printer Symbol }
> > >     DailyRate   : Double;               { Daily Rate }
> > >     CompanyRate : Double;               { Company Rate }
> > >     TriEuro     : SmallInt;
> > >     PadChar2    : Array [1..2] Of Char;
> > >         { Padding Character for Word Alignment }
> > >     TriRates    : Double;
> > >     TriInvert   : WordBool;
> > >     TriFloat    : WordBool;
> > >     PadChar1    : Array [1..3] Of Char;
> > >        { Padding Character for Word Alignment }
> > >     LastChar    : Char;
> > >        { Last Character in record - used for VB alignment }
> > > End; { TBatchCurrRec }
> > [snip]
> > > Line 1)     my $currency = new Win32::API
> > >                    ('Entdll32.dll', 'EX_GETCURRENCY', 'PNN', 'N');
> > [snip]
> > > Line 2)     my $struct_pack = pack("xxxxxxxxxxxx", 56);
> > > # x should be replaced by proper types, 56 defines the record
> > > # size.
> > > Line 3) my $currency_call = $currency->Call($struct_pack, 56, 1);
> > > # call to dll function
> > > Line 4)
> > > ($Name,$ScreenSymb,$PrinterSymb,$DailyRate,$CompanyRate,$TriEuro,
> > >  $PadChar2,$TriRates,$TriInvert,$TriFloat,$PadChar1,$LastChar)=
> > >   unpack("xxxxxxxxxxxx",56);
> > > Line 5)     print $Name;

> > use constant TBatchCurrRec => do { local $_ = q/
> >     Z11 # Name        : String[11];           { Currency name }
> >     Z3  # ScreenSymb  : String[3];            { Screen Symbol }
> >     Z3  # PrinterSymb : String[3];            { Printer Symbol }
> >     # Urm... 11+3+3 = 17.
> >     # To get a total of 56, these 3 fields need to = 16.
> >     d   # DailyRate   : Double;               { Daily Rate }
> >     d   # CompanyRate : Double;               { Company Rate }
> >     s   # TriEuro     : SmallInt;
> >     x2  # PadChar2    : Array [1..2] Of Char;
> >         # { Padding Character for Word Alignment }
> >     d   # TriRates    : Double;
> >     L   # TriInvert   : WordBool;
> >     L   # TriFloat    : WordBool;
> >     x3  # PadChar1    : Array [1..3] Of Char;
> >         # { Padding Character for Word Alignment }
> >     x   # LastChar    : Char;
> >         # { Last Character in record - used for VB alignment }
> >     # leaving off this 'Last Character' would also bring the total
> >     # to 56, I suppose.
> > /; s/\s*|#.*//g; $_ };

> > BEGIN {
> >    my $getcurrency = Win32::API->new(qw(
> >        Entdll32 EX_GETCURRENCY PNN N));
> >    sub GetCurrency($) {
> >       my $curr = shift;
> >       my $p = pack( TBatchCurrRec, () );
> >       $getcurrency->Call($p, length $p, $curr)
> >           or die "Error calling EX_GETCURRENCY: $^E";
> >       unpack TBatchCurrRec, $p;
> >    }
> > }

> > my ($Name, $ScreenSymb, $PrinterSymb, $DailyRate, $CompanyRate,
> >     $TriEuro, $TriRates, $TriInvert, $TriFloat) = GetCurrency(1);
> > print $Name, "\n";

> Thanks for the reply Benjamin. However, i'm still having trouble....I
> believe it's with the data type definition.

Maybe, maybe not.  What kind of error are you getting?

Quote:
> How does Perl know what the byte size is for a particular data type?

For some items, it's a constant, and for some it's system dependent.
See the pack() page.
    perldoc -f pack

Quote:
> I know it's defined in your code,

Commented, not defined in my code... it's defined somewhere in perl's
internals, in pp_pack.

Quote:
> but is that the actual byte size used?.....

Well, I hope so :) otherwise my code is wrong.

Quote:
> how can I display exactly how many bytes each string, double
> definition you've made is actually taking up?

To find out how many bytes a packed double takes, you can do:
   my $packed_double = pack("d", 0);
   print "Length of a packed double is: ".length($packed_double)."\n";

Unless the 'double' that the C compiler used to make perl is a different
size of double than the C compiler used to make VB, then this should be
fine.  On most machines windows runs on, double is 8 bytes, float is 4.

To find out how many bytes a packed word is, assume that 'int' and
'word' are exactly the same size, and use the "i" or "I" template (I use
the "L" template, which *might* be wrong.  But it probably isn't, unless
you're running windows somewhere that 'long' and 'word' are different
sizes).  On most machines windows run on, long is 4 bytes, and int is
either 2 or 4 bytes (but 2 wouldn't make sense for adding up to 56
bytes).

For the size of strings... Z11 is exactly 11 bytes, Z3 is exactly three
bytes.

Similarly, with the x template, the number given is the exact number of
bytes to skip.

Quote:
> Hope this question makes sense!
> Many thanks,
> Mort.

--
Found on a door in the MSU music building:
This door is baroquen, please wiggle Handel.
(If I wiggle Handel, will it wiggle Bach?)


Mon, 12 Jul 2004 21:32:19 GMT  
 
 [ 1 post ] 

 Relevant Pages 

1. HELP! Invoking a DLL function using Win32::API

2. Help: WIN32::API to dll interfacing: crash on return value

3. Invoking functions contained in DLLs

4. Win32::API and Novell DLL Pointers

5. Win32::API GetOpenFileName from comdlg32.dll

6. WIN32::API perl.dll is missing

7. Using API's from 3rd party dlls [Newie question]

8. Help about using win32::API

9. Problems calling a Win32 dll function

10. Passing NULL pointers to Win32::API function

11. Passing NULL pointer to Win32::API function

12. Win32::API and a callback function

 

 
Powered by phpBB® Forum Software