Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

Re: Win32::API Memory Exception with GetCommandLine() (which returns a static string)

by syphilis (Bishop)
on Jul 06, 2007 at 04:01 UTC ( #625182=note: print w/replies, xml ) Need Help??


in reply to Win32::API Memory Exception with GetCommandLine() (which returns a static string)

Hi Wyrdweaver,
When I run that batch file (as 'yrt.bat') I get the following output, followed by a GPF:
C:\_32\pscrpt\inline>yrt.bat string[21] = 'perl -x -S yrt.bat '
Here's the same batch file using Inline::C (which you could install and use, since you have MinGW) instead of Win32::API:
@rem = '--*-Perl-*-- @echo off if "%OS%" == "Windows_NT" goto WinNT perl -x -S "%0" %1 %2 %3 %4 %5 %6 %7 %8 %9 goto endofperl :WinNT perl -x -S %0 %* if NOT "%COMSPEC%" == "%SystemRoot%\system32\cmd.exe" goto endofperl if %errorlevel% == 9009 echo You do not have Perl in your PATH. if errorlevel 1 goto script_failed_so_exit_with_non_zero_val 2>nul goto endofperl @rem '; #!/usr/bin/perl -w #line 15 #use Inline C => Config => # BUILD_NOISY => 1; # See compilation output use Inline C => <<'EOC'; SV * wrap_GetCommandLine() { return newSVpv(GetCommandLine(), 0); } EOC my $string = wrap_GetCommandLine(); print "string[".length($string)."] = '$string'\n"; # ------ padding ----------------------------------------------------- +--------------------------------- __END__ :endofperl
The first time you run that there's some compilation takes place.Subsequent runs of the batch file will not require any compilation unless the actual Inline::C code is changed, or the name of the batch file is changed. Running that batch file (as try.bat), I get:
C:\_32\pscrpt\inline>try.bat string[20] = 'perl -x -S try.bat '
This time there's no GPF - I don't know why try.bat reports one less trailing space than yrt.bat.

Hope this helps.

Cheers,
Rob
Update:Or, if you want to modularise it (which would make better sense) here's a very minimalistic approach:
Makefile.PL
use ExtUtils::MakeMaker; my %options = %{ { 'NAME' => 'Win32::GetCommandLine', 'VERSION' => '0.01' } }; WriteMakefile(%options); # Remove the Makefile dependency. Causes problems on a few systems. sub MY::makefile { '' }
GetCommandLine.xs
#include "EXTERN.h" #include "perl.h" #include "XSUB.h" SV * wrap_GetCommandLine() { return newSVpv(GetCommandLine(), 0); } MODULE = Win32::GetCommandLine PACKAGE = Win32::GetCommandLine PROTOTYPES: DISABLE SV * wrap_GetCommandLine ()
t/test.t
use Win32::GetCommandLine; print "1..1\n"; my $string = Win32::GetCommandLine::wrap_GetCommandLine(); if($string =~ /perl/) {print "ok 1\n"} else {print "not ok 1\n"}
Win32/GetCommandLine.pm
package Win32::GetCommandLine; require DynaLoader; @ISA = qw(DynaLoader); $VERSION = '0.01'; bootstrap Win32::GetCommandLine $VERSION; 1;

Replies are listed 'Best First'.
Re^2: Win32::API Memory Exception with GetCommandLine() (which returns a static string)
by BrowserUk (Pope) on Jul 06, 2007 at 04:34 UTC

    At the core of Win32::API are several small piece of assembler code:

    #if (defined(__BORLANDC__) && __BORLANDC__ >= 452) #define ASM_LOAD_EAX(param,type) { \ __asm { \ mov eax, type param ; \ push eax ; \ } /* MSVC compilers */ #elif defined _MSC_VER /* Disable warning about one missing macro parameter. TODO: How we define a macro with an optional (empty) parameter? + */ #pragma warning( disable : 4003 ) #define ASM_LOAD_EAX(param,type) { \ __asm { mov eax, type param }; \ __asm { push eax }; \ } /* GCC-MinGW Compiler */ #elif (defined(__GNUC__)) #define ASM_LOAD_EAX(param,...) asm ("push %0" :: "g" (param)); #endif ... ASM_LOAD_EAX(pParam, dword ptr); ## many similar ... #if (defined(_MSC_VER) || defined(BORLANDC)) __asm { mov eax, dword ptr [dParam + 4] ; push eax ; mov eax, dword ptr [dParam] ; push eax ; }; #elif (defined(__GNUC__)) /* probably uglier than necessary, but works */ asm ("pushl %0":: "g" (((unsigned int*)&dParam)[1])); asm ("pushl %0":: "g" (((unsigned int*)&dParam)[0])); /* { int idc; printf ("dParam = "); for (idc = 0; idc < sizeof(dParam); idc++) { printf(" %2.2x",((unsigned char*)&dParam)[idc]); } printf(" %f\n", dParam); } */ #endif

    One has to suspect, if the OP confirms he is using a mingw built version of Perl that the problem lies in there somewhere. Does mingw build using similar calling conventions to MSC? That is the PASCAL calling convention for system apis.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      One has to suspect, if the OP confirms he is using a mingw built version of Perl that the problem lies in there somewhere

      There's a couple of different possibilities:
      1)It's MinGW-built perl using MinGW-built Win32::API;
      2)It's MinGW-built perl using VC-built Win32::API;

      I'm in the second category (with Win32-API-0.46). I also have Win32-API-0.46 on ActiveState perl (build 819) - it is exactly the same binary as I'm running on my MinGW-built perl, but there's no GPF with ActivePerl ... which leads me to the conclusion that the problem might lie outside Win32::API.

      I still get the same length discrepancy on ActivePerl - ie Inline's 20 vs Win32::API's 21.

      Cheers,
      Rob
        I still get the same length discrepancy on ActivePerl - ie Inline's 20 vs Win32::API's 21.

        I have a vague recollection that somewhere in Win32::API, they have code to extend the length of various strings/buffers passed in and/or out by one to 'allow room for terminating nulls'.

        Maybe I'm too tired or mis-remembering, because I cannot find it now? :(


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
Re^2: Win32::API Memory Exception with GetCommandLine() (which returns a static string)
by Wyrdweaver (Beadle) on Jul 07, 2007 at 18:02 UTC

    Thanks for the suggestion of "Inline::C". I hadn't seen that module before now. Unfortunately it's seems to be brittle on my system (failing because it didn't quote one of the Win32 directories with embedded spaces for gcc). However, it does produce a rough XS that I'll probably use quite a bit in the future.

    I'll probably end up using XS. And so, I should thank you again for showing me the basic XS template for this function.

      failing because it didn't quote one of the Win32 directories with embedded spaces for gcc

      Yes, there are problems with Inline::C and directory names that contain spaces. The problems are not insurmountable, but the best fix is to not install anything into a directory whose name contains any spaces.

      For the generation of the XS file and the Makefile.PL I just used InlineX::C2XS - ie, I placed a file named GetCommandLine.c (which contained just the solitary Inline::C function) in the ./src folder and ran
      perl -MInlineX::C2XS -e "InlineX::C2XS::c2xs('Win32::GetCommandLine',' +Win32::GetCommandline',{'WRITE_MAKEFILE_PL'=>1,'VERSION'=>0.01})"
      That creates the Makefile.PL and GetCommandLine.xs in the cwd. I then spent the next 15 minutes writing by hand GetCommandLine.pm (which I kept stuffing up) ... so I've now modified InlineX::C2XS::c2xs() to accept a 'WRITE_PM'=>1 argument that writes that .pm stub file as well. (This will be in the next CPAN release.)

      Note that there's more than one way to write an XS file (oO ... deja vu :-). The rendition that I posted is the way that Inline::C (which is used by InlineX::C2XS) autogenerated it.

      Cheers,
      Rob

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://625182]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others lurking in the Monastery: (2)
As of 2021-10-19 06:38 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    My first memorable Perl project was:







    Results (76 votes). Check out past polls.

    Notices?