Professional Web Applications Themes

Apparent bug in Win32::API if function returns a float or a double - PERL Modules

Summary: there appears to be a bug with the perl module Win32::API, calling functions that return a float or a double. *** I have eliminated the "stdcall v cdecl" newby-trap as an explanation! *** I have tested the problem under two environments: A fresh install of ActivePerl-5.10.0.1003-MSWin32-x86-285500.msi * Install folder changed from default to C:\Perl510 * This build includes Win32::API v0.55 * No further modules were installed * I modified my command-prompt environment as follows: set PERL5LIB=C:\Perl510;C:\Perl510\bin;C:\Perl510\site ;C:\Perl510\site\lib set PERLLIB=C:\Perl510;C:\Perl510\bin;C:\Perl510\site; C:\Perl510\site\lib PATH C:\Perl510\bin;c:\windows;c:\windows\system32 A fresh install of ActivePerl-5.8.8.822-MSWin32-x86-280952.msi * Install folder changed from default to C:\Perl58 * From the C:\Perl58\bin ...

  1. #1

    Default Apparent bug in Win32::API if function returns a float or a double

    Summary: there appears to be a bug with the perl module Win32::API, calling
    functions that return a float or a double.

    *** I have eliminated the "stdcall v cdecl" newby-trap as an explanation!
    ***


    I have tested the problem under two environments:

    A fresh install of ActivePerl-5.10.0.1003-MSWin32-x86-285500.msi
    * Install folder changed from default to C:\Perl510
    * This build includes Win32::API v0.55
    * No further modules were installed
    * I modified my command-prompt environment as follows:
    set
    PERL5LIB=C:\Perl510;C:\Perl510\bin;C:\Perl510\site ;C:\Perl510\site\lib
    set
    PERLLIB=C:\Perl510;C:\Perl510\bin;C:\Perl510\site; C:\Perl510\site\lib
    PATH C:\Perl510\bin;c:\windows;c:\windows\system32


    A fresh install of ActivePerl-5.8.8.822-MSWin32-x86-280952.msi
    * Install folder changed from default to C:\Perl58
    * From the C:\Perl58\bin folder I performed the following, which installed
    Win32::API v 0.53
    ppm.bat install Win32-API
    * I modified my command-prompt environment as follows:
    set PERL5LIB=C:\Perl58;C:\Perl58\bin;C:\Perl58\site;C: \Perl58\site\lib
    set PERLLIB=C:\Perl58;C:\Perl58\bin;C:\Perl58\site;C:\ Perl58\site\lib
    PATH C:\Perl58\bin;c:\windows;c:\windows\system32


    I have written a simple DLL that exports three functions:
    int __stdcall MyStrToInt (char* aStr);
    float __stdcall MyStrToFloat (char* aStr);
    double __stdcall MyStrToDouble (char* aStr);

    I have tested that DLL by calling all three functions from another
    executable.
    *** I have VERIFIED that the functions are exported with the "stdcall"
    calling convention. ***


    When I call MyStrToInt() from perl, it works correctly
    When I call either MyStrToFloat() or MyStrToDouble(), the process fails. The
    error dialog begins...
    Perl Command Line Interpreter has encountered a
    problem and needs to close. We are sorry for the
    inconvenience.


    I have succeeded in debugging the call to my DLL inside my IDE.
    The failed function is called TWICE, which to me suggests confusion about
    how many bytes are pushed or popped from the stack.
    If my ysis is correct, the "RET" instruction is seeing my function's
    address on the stack instead of the return address setup by the caller.

    my perl script follows:
    ########################
    use Win32::API;

    #print "Press Enter\n";
    #<STDIN>;

    my ($dllname,$function,$return,$doubleret,$floatret);
    $dllname = 'tmdll.dll';

    ########################
    ##### MyStrToInt() #####
    ########################

    print "Calling API->new to get handle to MyStrToInt()\n";
    $function = Win32::API->new($dllname, 'MyStrToInt', 'P', 'I');

    print "Calling tmDLL MyStrToInt()\n";
    $return = $function->Call("123");
    print "HYDLL MyStrToInt() returned $return\n";


    ##########################
    ##### MyStrToFloat() #####
    ##########################

    print "Calling API->new to get handle to MyStrToFloat()\n";

    $function = Win32::API->new($dllname, 'MyStrToFloat', 'P', 'F');
    print "Calling tmDLL MyStrToFloat()\n";

    $floatret = $function->Call("123");
    print "HYDLL MyStrToFloat() returned $floatret\n";


    ###########################
    ##### MyStrToDouble() #####
    ###########################

    print "Calling API->new to get handle to MyStrToDouble()\n";
    $function = Win32::API->new($dllname, 'MyStrToDouble', 'P', 'D');

    print "Win32::API-New returned undef\n" if(!defined($function));
    print "Calling tmDLL MyStrToDouble()\n";

    $doubleret = $function->Call("123");
    print "HYDLL MyStrToDouble() returned $doubleret\n";


    Trevor Guest

  2. #2

    Default Apparent bug in Win32::API if function returns a float or a double

    Summary: there appears to be a bug with the perl module Win32::API,
    calling functions that return a float or a double.

    *** I have eliminated the "stdcall v cdecl" newby-trap as an
    explanation! ***


    I have tested the problem under two environments:

    A fresh install of ActivePerl-5.10.0.1003-MSWin32-x86-285500.msi
    * Install folder changed from default to C:\Perl510
    * This build includes Win32::API v0.55
    * No further modules were installed
    * I modified my command-prompt environment as follows:
    set PERL5LIB=C:\Perl510;C:\Perl510\bin;C:\Perl510\site ;C:
    \Perl510\site\lib
    set PERLLIB=C:\Perl510;C:\Perl510\bin;C:\Perl510\site; C:
    \Perl510\site\lib
    PATH C:\Perl510\bin;c:\windows;c:\windows\system32


    A fresh install of ActivePerl-5.8.8.822-MSWin32-x86-280952.msi
    * Install folder changed from default to C:\Perl58
    * From the C:\Perl58\bin folder I performed the following, which
    installed Win32::API v 0.53
    ppm.bat install Win32-API
    * I modified my command-prompt environment as follows:
    set PERL5LIB=C:\Perl58;C:\Perl58\bin;C:\Perl58\site;C:
    \Perl58\site\lib
    set PERLLIB=C:\Perl58;C:\Perl58\bin;C:\Perl58\site;C:
    \Perl58\site\lib
    PATH C:\Perl58\bin;c:\windows;c:\windows\system32


    I have written a simple DLL that exports three functions:
    int __stdcall MyStrToInt (char* aStr);
    float __stdcall MyStrToFloat (char* aStr);
    double __stdcall MyStrToDouble (char* aStr);

    I have tested that DLL by calling all three functions from another
    executable.
    *** I have VERIFIED that the functions are exported with the "stdcall"
    calling convention. ***


    When I call MyStrToInt() from perl, it works correctly
    When I call either MyStrToFloat() or MyStrToDouble(), the process
    fails. The error dialog begins...
    Perl Command Line Interpreter has encountered a
    problem and needs to close. We are sorry for the
    inconvenience.


    I have succeeded in debugging the call to my DLL inside my IDE.
    The failed function is called TWICE, which to me suggests confusion
    about how many bytes are pushed or popped from the stack.
    If my ysis is correct, the "RET" instruction is seeing my
    function's address on the stack instead of the return address setup by
    the caller.

    my perl script follows:
    ########################
    use Win32::API;

    #print "Press Enter\n";
    #<STDIN>;

    my ($dllname,$function,$return,$doubleret,$floatret);
    $dllname = 'tmdll.dll';

    ########################
    ##### MyStrToInt() #####
    ########################

    print "Calling API->new to get handle to MyStrToInt()\n";
    $function = Win32::API->new($dllname, 'MyStrToInt', 'P', 'I');

    print "Calling tmDLL MyStrToInt()\n";
    $return = $function->Call("123");
    print "HYDLL MyStrToInt() returned $return\n";


    ##########################
    ##### MyStrToFloat() #####
    ##########################

    print "Calling API->new to get handle to MyStrToFloat()\n";

    $function = Win32::API->new($dllname, 'MyStrToFloat', 'P', 'F');
    print "Calling tmDLL MyStrToFloat()\n";

    $floatret = $function->Call("123");
    print "HYDLL MyStrToFloat() returned $floatret\n";


    ###########################
    ##### MyStrToDouble() #####
    ###########################

    print "Calling API->new to get handle to MyStrToDouble()\n";
    $function = Win32::API->new($dllname, 'MyStrToDouble', 'P', 'D');

    print "Win32::API-New returned undef\n" if(!defined($function));
    print "Calling tmDLL MyStrToDouble()\n";

    $doubleret = $function->Call("123");
    print "HYDLL MyStrToDouble() returned $doubleret\n";
    trevors_decoy@hotmail.com Guest

  3. #3

    Default Re: Apparent bug in Win32::API if function returns a float or adouble

    On May 22, 2:05pm, "Trevor Magnusson"
    <com.au> wrote: 

    Which compiler did you use to build the dll ?

    I prefer to use Inline::C to access external libraries as I find it
    more logical (less intuitive). Inline::C can also provide better
    mileage. However, I think that Win32::API should not be presenting the
    problems you're experiencing. So I'm inclined to think that you're
    doing something you ought not be doing ... but I just can't (yet) put
    my finger on it.

    If you answer the question I've asked I'll take a closer look
    (tomorrow night - when I have more time up my sleeve).

    Hopefully, by then, soemone else will have solved the issue for
    you :-)

    Cheers,
    Rob

    sisyphus Guest

  4. #4

    Default Re: Apparent bug in Win32::API if function returns a float or a double

    > Which compiler did you use to build the dll ?

    I used Delphi, I hope that doesn't lower my cred ;)

    However, I have quite a lot of experience at both exposing and consuming
    DLLs across the Delphi / C++ boundary, and I'm certain that is not the
    source of the problem. Delphi allows you to specify stdcall / cdecl, and
    I've verified I was doing that correctly.

     

    One of my colleagues has suggested I investigate something called XS...


    Trevor Guest

  5. #5

    Default Re: Apparent bug in Win32::API if function returns a float or adouble

    On May 23, 12:39pm, "Trevor Magnusson"
    <com.au> wrote:
    .


    Yes, Inline::C auto-generates the XS code for you - saves you the
    trouble of writing the XS file (and the other files that you need to
    write in order to create the extension).

    I'm using the MinGW prot of gcc as my Windows compiler.
    First up I created double.c:

    -------------------------
    #include <stdlib.h>

    double __declspec(dllexport) my_double(char * num) {
    char * foo;
    double ret;
    ret = strtod(num, &foo);
    return ret;
    }

    -------------------------

    Then built the object file by running:

    gcc -o double.o -c double.c

    Then built the dll (and the import lib, libdouble.a) by running:

    gcc -shared -o double.dll double.o -Wl,--out-implib,libdouble.a

    I tried to get it to work with Win32::API ... but kept getting
    segfaults. I even tried using VC 7.0 (on another machine) to build the
    dll, but couldn't get that to work, either. (I still think it should
    be workable - but I don't personally care all that much, and got sick
    of trying.)

    With Inline::C, it's fairly trivial:

    ----------------------------
    use warnings;
    #use Devel::Peek;
    use Inline C => Config =>
    LIBS => '-LC:/_32/C -ldouble', # relative path won't do
    BUILD_NOISY => 1; # view build output

    use Inline C => <<'EOC';

    double my_double(char*); // prototype

    double foo(char * x) {
    return my_double(x);
    }

    EOC

    $ret = foo('123');
    print $ret;
    #Dump($ret);
    ----------------------------

    With MS compilers, Inline::C (and XS) will need to access the import
    lib. Win32::API can access the dll directly.
    With the gcc compiler, Inline::C (and XS) can access the dll directly,
    though the above script accesses the import lib (libdouble.a) instead.

    If you have Devel::Peek installed you can uncomment those 2 lines in
    the above script and verify that the returned value is, in fact, of
    type NV (SVNV) - which is the perl equivalent of a double.

    Cheers,
    Rob

    sisyphus Guest

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139