No, there's doesn't appear to be. In some circumstances and probably all circumstances, it calls a C function directly. At the very least, it would require a recompile.
Your best bets would be to override List::Util::shuffle with your own (XS or PP) version or to provide your own local (XS or PP) version List::Util.
| [reply] |
I've been using a perl shuffle routine, but it is so slow compared to List::Util's version.
I can re-compile util.xs easily enough, but I'm unsure about how to call a routine located in another XS module from within an XS module. Any thoughts, or examples?
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.
| [reply] |
Math::Random::MT's rand is actually a Perl function.
srand is an XS function, so it expects to be called from Perl.
You'll need to use one of the methods in perlcall in both cases.
If you wanted to bypass Perl, you'd have to convert MT.pm and MT.xs to C, then compile and link MT.c, the converted code and your version of List/Util.c together.
| [reply] [d/l] [select] |
I'm unsure about how to call a routine located in another XS module from within an XS module
One solution - if, in Foo.xs, we want to access a function (let's call it 'bar') from Bar.xs, then we have the Bar module make available a pointer to the bar function. The Foo.xs functions then access the bar function via that pointer.
I have a full but minimal working demo of this principle on this machine. I could put copies of the files (Foo.pm, Bar.pm, Foo.xs, Bar.xs, Makefile.PL's and test.pl's) on my scratchpad if that's going to serve any purpose. Note that, with this approach, you'll probably be making significant alterations to both source distros. I think it's the best approach to calling xsubs in one extension from xsubs in another extension .... but I'm not so sure that this is the best way for you to achieve your ends in this particular case.
For a basic demo of passing functions by pointer, here's an Inline::C script that creamygoodness posted a while back:
use strict;
use warnings;
use Inline C => Config =>
BUILD_NOISY => 1;
use Inline C => <<'END_C';
typedef void
(*hello_func_t)(SV * x);
typedef SV *
(*sv_func_t)(SV * x);
void
hola_mundo(SV * x)
{
printf("Hola, mundo! %d\n", (int)SvIV(x));
}
SV *
hola_mundo2(SV *x) {
printf("Hola, mundo2! %d\n", (int)SvIV(x));
return newSViv((int)SvIV(x) * 2);
}
SV*
get_hola_mundo_func_ptr()
{
return newSViv( PTR2IV(hola_mundo) );
}
SV*
get_hola_mundo2_func_ptr()
{
return newSViv( PTR2IV(hola_mundo2) );
}
void
do_hello(SV *sv_with_func_ptr, SV * x)
{
IV temp = SvIV(sv_with_func_ptr);
hello_func_t hello = INT2PTR(hello_func_t, temp);
hello(x);
}
SV *
do_hello2(SV *sv_with_func_ptr, SV * x)
{
IV temp = SvIV(sv_with_func_ptr);
sv_func_t hello = INT2PTR(sv_func_t, temp);
return hello(x);
}
END_C
my $num = 123458;
my $func_ptr = get_hola_mundo_func_ptr();
do_hello($func_ptr, $num);
my $func_ptr2 = get_hola_mundo2_func_ptr();
my $ret = do_hello2($func_ptr2, $num);
print $ret;
Cheers, Rob | [reply] [d/l] |