Hi,

(This almost certainly has little, if anything, to do with perl.)

I have (a commercial version of) VC 7.0, and a perl-5.10.0 built using that
compiler.
I also have MinGW, and a perl-5.10.0 built using that MinGW compiler.

I have a test dll (named mydll.dll) that exports a function named 
'd_one_arg'.
That function takes a single 'int' arg, and returns the value of that int
divided by 7. (The return value is a double.)

In a nutshell, there's no problem with MinGW, but with VC 7.0 the following
Inline::C script always segfaults around the time that the foo() function 
exits:

------------------------------------------------
use warnings;
use Inline C => Config =>
    BUILD_NOISY => 1;

use Inline C => <<'EOC';

typedef double (CALLBACK* FUNC2)(int);

SV * load_library (SV * dll) {
     return newSVuv((HMODULE)LoadLibrary((LPCTSTR)SvPV_nolen(dll)));
}

SV * foo(SV * x, SV * hinstLib) {
    FUNC2 ProcAdd;
    BOOL freelib, fRunTimeLinkSuccess = FALSE;
    double ret = 0;

    if ((HMODULE)SvUV(hinstLib) != NULL) {
        ProcAdd = (FUNC2) GetProcAddress((HMODULE)SvUV(hinstLib), 
"d_one_arg");

        if (fRunTimeLinkSuccess = (ProcAdd != NULL)) {
            ret = ProcAdd((int)SvIV(x));
        }

        else printf("GetProcAddress() failed\n");

        freelib = FreeLibrary((HMODULE)SvUV(hinstLib));
        printf("freelib: %d\nreturn: %f\n", freelib, ret);
        return newSVnv(ret);
    }

    else {
        printf("LoadLibrary() failed\n");
        return newSVnv(ret);
    }
}

EOC
$lib = load_library("mydll");
$z = foo(123, $lib);
print $z, "\n";
------------------------------------------------

It makes no difference if $lib is instead assigned the return value of 
Win32::LoadLibrary("mydll").
It makes no difference whether the dll was built using MinGW or VC 7.0.

Running that script in the VC 7.0 environment produces:

freelib: 1
return: 17.571429
[Then a segfault]

So, I'm thinking the segfault is caused by either:
a) 'return newSVnv(ret);'
or
b) the exiting of the foo() function;
or
c)'print $z, "\n";'

If I rewrite foo() so that it loads the mydll.dll library itself (instead of 
taking a handle to it as its second arg) then there's no problem. That is, 
there's no problem if foo() looks like:

-------------------------------------------
SV * foo(SV * x) {
    HMODULE hinstLib;
    FUNC2 ProcAdd;
    BOOL freelib, fRunTimeLinkSuccess = FALSE;
    double ret = 0;

    hinstLib = LoadLibrary("mydll");

    if (hinstLib != NULL) {
        ProcAdd = (FUNC2) GetProcAddress(hinstLib, "d_one_arg");

        if (fRunTimeLinkSuccess = (ProcAdd != NULL)) {
            ret = ProcAdd((int)SvIV(x));
        }

        else printf("GetProcAddress() failed\n");

        freelib = FreeLibrary(hinstLib);
        printf("freelib: %d\nreturn: %f\n", freelib, ret);
        return newSVnv(ret);
    }

    else {
        printf("LoadLibrary() failed\n");
        return newSVnv(ret);
    }
}
-------------------------------------------

That (correctly) produces:

freelib: 1
return: 17.571429
17.5714285714286

So what is it that causes the first version of foo() to segfault ?

(I've also tried things out on a perl-5.8.8 built with the VC 7.0 compiler, 
and the behaviour there is exactly the same as for 5.10.0.)

Cheers,
Rob


_______________________________________________
Perl-Win32-Users mailing list
[email protected]
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs

Reply via email to