Hi,

Consider the function:

void do_something(int len) {
     /* do stuff */
     }

I always thought that was equivalent to :

void do_something(SV * size) {
     int len = SvIV(size);
     /* do exactly same stuff */
     }


But I've just been doing a wrapper of the GetTempPath() function that's in the Windows kernel32.dll.


The following works:

SV * gettemppath(int size) {
     char * buffer;
     GetTempPath(size, buffer);
     return newSVpv(buffer, 0);
     }

But the following segfaults before the script outputs anything (though it compiles fine, and without issuing any warnings):

SV * gettemppath(SV * size) {
     char * buffer;
     GetTempPath(SvIV(size), buffer);
     return newSVpv(buffer, 0);
     }

In both cases I've called the function from perl with:

print gettemppath(80), "\n";

The idea is that the argument supplied to the gettemppath() function (ie 80) determines the size (in characters) of the buffer that stores the path string. It therefore has to be large enough to hold the string (which it is). It doesn't matter if it's larger than the length of the path string (which it also is).

The following also segfaults (and also compiles without issuing any warnings):

SV * gettemppath(SV * size) {
     int len = SvIV(size);
     char * buffer;
     GetTempPath(len, buffer);
     return newSVpv(buffer, 0);
     }

In this case, however, the script actually gets to print the (correct) temp path before the segfault occurs.

I've always had my Inline::C functions receive int's as SV*'s and never struck any trouble. I'm a little puzzled as to why this has now suddenly surfaced. Something to do with the Windows API, perhaps ? .... or too many Bourbons ? .... or not enough Bourbons ?

A 'diff -u' on the '.c' files produced presents me with a set of differences that are exactly as expected.

Of course I can simply rewrite gettemppath as:

SV * gettemppath() {
     char * buffer;
     GetTempPath(80, buffer);
     return newSVpv(buffer, 0);
     }

That also works fine - but doesn't really solve the puzzle :-)

I'm unable to reproduce the problem using generic C functions - it only seems to be happening with this Windows API function.

I'm running Windows2000 and it's the same behaviour with both perl 5.6.1 and 5.8.4 (both perls built with dmake and MinGW).

Below is a copy'n'paste of the actual script (one of the failing versions) I'm running. The code above, having been typed, not copied, may be riddled with typos.

Cheers,
Rob

use warnings;
use Inline (C => Config =>
            LIBS => '-lkernel32',
            BUILD_NOISY => 1,
            USING => 'ParseRegExp',
            );

use Inline C => <<'EOC';

#include <windows.h>

SV * gettemppath(SV * len) {
     int size = SvIV(len);
     char * buffer;
     GetTempPath(size, buffer);
     return newSVpv(buffer, 0);
}

EOC

print gettemppath(80), "\n";

__END__

prints:
C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\
then segfaults.




Reply via email to