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

Hi,
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    This is a pointer to a specific type of record *see below
PSize    This is the length of the record that the P parameters points to,
this is used by the DLL to check it is receiving the correct record size.
Curr    This indicates the currency number that you want to retrieve the
information about.
----------------------------------------------------------------------------
---------------------------------------------------------------------------

* 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 }

Record length = 56 Bytes
----------------------------------------------------------------------------
---------------------------------------------------------------------------

As can be seen, the function expects a pointer and two integer values as
arguments. It's return value is an integer.
I begin my code by creating a new Win32::API object:

Line 1)     my $currency = new Win32::API ('Entdll32.dll', 'EX_GETCURRENCY',
'P,N,N', 'N');

Now as far as i'm aware, to pass a pointer to a structure in C,  I will need
to pack() the required elements in a variable. Then to access the values
stored in a structure, I'll have to unpack() it as required. I have seen
code for doing this, but it dealt with a record structure consisting of just
2 Longs for example. I need to know how to deal with strings, doubles,
arrays, words etc as can be seen from the record structure. The basic
outline of my code will be something like this:

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;

With regard to Lines 2 and 4, I'm at a loss! I'm not sure how to pack and
unpack various record attributes or whether i should be including the record
size in the pack/unpack function calls. I was wondering if there was
somebody out there who could help me and fill in the blanks (i.e. modify
lines 2 and 4!!). Basically, what I need to do overall is to call the
ex_getcurrency dll function from a perl script, and display the currency
name.

Many thanks,
Mort.



Sat, 10 Jul 2004 03:31:15 GMT  
 HELP! Invoking a DLL function using Win32::API

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;
   }

Quote:
}

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

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



Sun, 11 Jul 2004 14:59:45 GMT  
 
 [ 2 post ] 

 Relevant Pages 

1. TechTips: Designing safer apps using local tables

2. How to scroll text?

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

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

5. Invoking functions contained in DLLs

6. Delphi, IB, and SQL Token problems

7. Deleting directories from options menu.

8. My BBS Source Site

9. Win32::API and Novell DLL Pointers

10. Win32::API GetOpenFileName from comdlg32.dll

11. WIN32::API perl.dll is missing

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

 

 
Powered by phpBB® Forum Software