Calling multiple perl subroutines from XS procedure
by Marcin Kasperski » Tue, 20 Jul 2004 22:49:06 GMT
XS manual pages, "Advanced perl programming" etc all mention the
more-or-less such sequence to be used while calling perl subroutine
from C code:
{
dSP;
ENTER;
SAVETMPS;
PUSHMARK(sp);
/* ... populating params with XPUSHs */
PUTBACK;
int n = perl_call_method(...); /* Or perl_call_pv or similar */
/* ... reading return values with POPs */
SPAGAIN;
PUTBACK;
FREETMPS;
LEAVE;
}
my question, for which I could not find the answer, is: which of those
macros must I repeat and which can I reuse while calling MORE THAN ONE
perl subroutine. In other words, how can the code below be
simplified/shortened:
int somefun()
{
SV *val = 0;
{
dSP;
ENTER;
SAVETMPS;
PUSHMARK(sp);
XPUSHs(sv_2mortal(newSVpv("someparam", 0)));
PUTBACK;
int n = perl_call_pv("somefun", G_SCALAR);
if( n == 1 )
{
val = newSVsv(POPs);
}
SPAGAIN;
PUTBACK;
FREETMPS;
LEAVE;
if( ! val)
croak("something is wrong");
}
{
dSP;
ENTER;
SAVETMPS;
PUSHMARK(sp);
XPUSHs(val);
PUTBACK;
int n = perl_call_pv("otherfun", G_DISCARD);
SPAGAIN;
PUTBACK;
FREETMPS;
LEAVE;
}
}
(code above compiled with C++ compiler so anonymous { .. } can be used)
I suspect I can move dSP to the top of the function and use it only
once but what with ENTER, SAVETMPS etc? Can I for instance use
SAVETMPS once and FREETMPS once? What about ENTER/LEAVE?
----- End forwarded message -----
Re: Calling multiple perl subroutines from XS procedure
by Andrei Voropaev » Wed, 21 Jul 2004 16:49:19 GMT
In my expirience (and after checking source codes) you don't need
anonymous { ... } at all. Just put dSP; at the top of function and
then use ENTER; SAVETMPS; ... FREETMPS; LEAVE; before the call to
routine. The main idea of ENTER is to define scope for local variables.
So if you run routines within the same scope then probably nothing
terrible would happen (though I didn't try it). Just to summarize. I
usually write the above function as
int somefun()
{
dSP;
SV *val = 0;
ENTER;
SAVETMPS;
PUSHMARK(sp);
XPUSHs(sv_2mortal(newSVpv("someparam", 0)));
PUTBACK;
int n = perl_call_pv("somefun", G_SCALAR);
if( n == 1 )
{
val = newSVsv(POPs);
}
SPAGAIN;
PUTBACK;
FREETMPS;
LEAVE;
if( ! val)
croak("something is wrong");
ENTER;
SAVETMPS;
PUSHMARK(sp);
XPUSHs(val);
PUTBACK;
int n = perl_call_pv("otherfun", G_DISCARD);
SPAGAIN;
PUTBACK;
FREETMPS;
LEAVE;
}
Maybe you can leave only one pair of ENTER; SAVETMPS and FREETMPS;
LEAVE; And stack manipulation have to stay as it is.
Andrei
----- End forwarded message -----
Re: Calling multiple perl subroutines from XS procedure
by Marcin Kasperski » Wed, 21 Jul 2004 21:21:23 GMT
Could anyone confirm whether it is safe? I will probably have
situation where I call some perl subroutine within the loop so it is
likely that calling ENTER, SAVETMPS, FREETMPS and LEAVE once instead
of calling it at every loop iteration will give me some gain - but I
would not like to get strange errors...
So the question is: can I do:
(only once)
ENTER;
SAVETMPS;
(sequence below repeated a few or maybe even a lot of times)
PUSHMARK(sp);
(...XPUSHsing parameters...)
PUTBACK;
int n = perl_call_pv("otherfun", G_DISCARD);
SPAGAIN;
(...POPsing output...)
PUTBACK;
(only once)
FREETMPS;
LEAVE;
And the releated question: can I croak before calling FREETMPS and
LEAVE? Will I leak memory if croaking then?
----- End forwarded message -----
Similar Threads:
1.calling mysql stored procedure through perl
Hi,
I had been trying to call mysql stored procedure, but not able to do
it successfully.
The usage and error that i received are as follows:
*************************************************
Usage:
my $sth=$dbh->prepare(qq{call getme()});
$sth->execute() or die("SQL Error:- $DBI::errstr\n");
Error:
DBD::mysql::st execute failed: PROCEDURE test.getme can't return a
result set in the given context at line 11.
*************************************************
It'll be great if you could pls. guide me how to do that.
Thanks and Regards,
Vinod
2.calling Oracle stored procedure from Perl running on unix box
3.perl crash using Win32::API Call procedure
I'm trying to use the Win32::API module to call a simple test case DLL
(call it "addValues.dll"). My DLL has a function in it called
addValues:
extern "C" __declspec(dllexport)
double addValues(double a, double b) {
double c;
c = a + b;
cout << a << " " << b << " " << c << endl;
return(c);
}
My perl script to call this looks like:
use Win32::API;
$num1 = $ARGV[0];
$num2 = $ARGV[1];
$myFunc =
Win32::API->new('addValues', 'double addValues(double a, double
b)');
$out = $myFunc->Call($num1, $num2);
print "$out";
When executing this, perl bombs at the Call line, giving me the "Perl
Command Line Interpreter has encountered a problem and needs to close.
We are sorry for the inconvenience" message.
Note that if I change my dll function to take no arguments (hard coding
a and b within the function) and return a double, I have no problems,
e.g.
$myFunc = Win32::API->new('addValues', 'double addValues()');
$out = $myFunc->Call();
I have also tried the alternative calling syntax:
$myFunc = Win32::API->new('addValues', 'addValues', 'DD', 'D')
with no success. I'm very likely doing something stupid I know ...
4.Calling a SQL Server Stored Procedure from within Perl
Hi,
I'm trying to call a simple Stored Procedure from within my Perl
script. I tested the SP named "usp_test" in the Query Analyzer and it
ran OK. My perl script looks like this
use Win32::ODBC;
if (!($MyDB = new Win32::ODBC("DSN=MyDSN;UID=MyLoginID;PWD=MyPwd;")))
{
print "Error: Unable to connect to the database\n";
exit;
}
The connection is OK, I've tested it by listing all the rows in a test
table. Now I have to call the SP. I tried something like this but that
didn't work:
my $sth = $MyDB -> prepare("EXEC usp_test");
$sth -> execute;
Any information is welcome.
Thanks,
Ab
5.Call PL/SQL procedure from Perl - DBI
Hi,
How I can call PL/SQL store procedure from Perl - DBI script?
Thanks in advance,
Alex
6. How do I call a stored procedure using perl DBI and evaluate the output
7. calling stored procedure from Perl code
8. Calling a DB/2 v8.2 stored procedure from perl