syphilis has asked for the wisdom of the Perl Monks concerning the following question:

Hi,

(This is one of those types of posts that I don't like to read ... and like even less to write. Apologies in advance.)

The C library in question is gsl-1.11 (which is the latest release of that library, iinm).
The function in question is gsl_set_error_handling_off - which, when called, is supposed to disable inbuilt error handling in certain specific functions within the gsl-1.11 C library.
I have no problem in using that function in my C programs.

In Inline::C I've wrapped that function as:
void wrap_error_handler_off() { gsl_set_error_handler_off(); }
And that works fine - calling wrap_error_handler_off() does what it is supposed to do. That is, having called wrap_error_handler_off(), when I subsequently call these other "certain specific functions" (which have also been wrapped), I find that their inbuilt error handling has in fact been disabled as expected.

But, if I put the exact same wrapping into a module's XS file, it doesn't work ... it's not that any errors are produced (there are none) ... it's just that calling MyMod::wrap_error_handler_off() has no effect whatsoever. One might just as well not call the function at all.

Has anyone ever seen anything like this ? I've wrapped a few C libraries in my time, and I certainly haven't.

One other aspect to this is that it seems to be a Win32-specific issue - linux, at least, is *not* subject to this strange behaviour. On linux, the disablng works fine, irrespective of whether we're calling the function in Inline::C, or from within some particular namespace (module/extension).

The latest Math::GSL test suite relies on the functionality of the wrapping of gsl_set_error_handler_off. That test suite runs fine on linux. On win32 there are failures because of this very problem.

Any inkling as to what might be happening (and what to do about it) would be most enlightening.

Cheers,
Rob

Replies are listed 'Best First'.
Re: [XS] Bizarre (scoping ?) problem with wrapping C library function (2 dlls)
by tye (Sage) on Aug 13, 2008 at 16:04 UTC

    My first guess would be that the XS case ends up loading two different instances of the library and so the XS code is changing the behavior of the "wrong one". Hope that helps. I think that's the best I can do with the information provided.

    - tye        

      My first guess would be that the XS case ends up loading two different instances of the library

      Yes - I'll try to keep my mind open to that possibility as I plod on. Admittedly, I haven't provided very much for anyone ot work with - though I, myself, don't have much more to work with anyway.

      I've written a basic Inline::C script (below my sig) that works fine. It has just 2 functions - namely wrap_eror_handler_off and demo2_e. The first turns off the error handling, and the second enables me to check that the error handling has, in fact, been turned off. (If the error handling is off, demo2_e returns a nan. Otherwise it dies most ungracefully with a 'domain error' from the gsl C library. This is all expected behaviour.)

      And I've created a minimalist module (SIS::GSL) that contains the exact same 2 functions (nothing more, nothing less). The XS file that Inline::C generates, and the XS file that I have for SIS::GSL are *identical*, except that whereas Inline::C's XS file specifies:
      MODULE = gsl_error_pl_4227 PACKAGE = main
      SIS::GSL's XS file specifies:
      MODULE = SIS::GSL PACKAGE = SIS::GSL
      That's the only difference in the respective XS files. I've even gone so far as to rework SIS::GSL with the XS file containing:
      MODULE = SIS::GSL PACKAGE = main
      That successfully transfers wrap_eror_handler_off and demo2_e into the 'main' namespace, but wrap_eror_handler_off still fails to do what it is supposed to do.

      Maybe I need to take a closer look at what the gsl library's gsl_set_error_handler_off is doing.

      Thanks, tye.

      Cheers,
      Rob
      use warnings; use strict; use Inline C => Config => #BUILD_NOISY => 1, #CLEAN_AFTER_BUILD => 0, INC => '-IC:/_32/msys/1.0/local/include', LIBS => '-LC:/_32/msys/1.0/local/lib -lgslcblas -lgsl'; use Inline C => <<'EOC'; #include <stdio.h> #include <gsl/gsl_math.h> #include <gsl/gsl_errno.h> #include <gsl/gsl_sf_gamma.h> #include <gsl/gsl_sf_coupling.h> #include <gsl/gsl_message.h> void wrap_error_handler_off() { gsl_set_error_handler_off(); } SV * demo2_e(int a1, int a2, int a3, int a4, int a5, int a6, int a7, i +nt a8, int a9) { gsl_sf_result r; gsl_sf_coupling_9j_e(a1, a2, a3, a4, a5, a6, a7, a8, a9, &r); return newSVnv(r.val); } EOC wrap_error_handler_off(); # '-2' is an invalid argument, so the following # returns a nan iff error handler is turned off. # Otherwise it dies with 'domain error' my $r = demo2_e(4, -2, 4, 3, 3, 2, 1, 1, 2); print $r, "\n";