After wrestling with JPL for a number of weeks with no resolve we decided to attempt to write our own mechanism to bridge the
Java - C - Perl gap.
After another number of weeks we have managed to successfully execute a request from Java to C to Perl. However when why try to use a Perl library within the Perl procedure being called a rather nasty error is occuring.
# java com/rtel/TestCall
Loading...
...ok
before call...
Loading Perl <sxiConn.pl> file...
Can't load '/usr/local/lib/perl5/5.8.4/sun4-solaris/auto/Sys/Hostname/Hostname.so' for module Sys::H
ostname: ld.so.1: java: fatal: relocation error: file /usr/local/lib/perl5/5.8.4/sun4-solaris/auto/S
ys/Hostname/Hostname.so: symbol PL_stack_max: referenced symbol not found at /usr/local/lib/perl5/5.
8.4/sun4-solaris/XSLoader.pm line 68.
at /usr/local/lib/perl5/5.8.4/sun4-solaris/Sys/Hostname.pm line 23
Can't load '/usr/local/lib/perl5/site_perl/5.8.4/sun4-solaris/auto/SVRQ/SVRQ.so' for module SVRQ: ld
.so.1: java: fatal: relocation error: file /usr/local/lib/perl5/site_perl/5.8.4/sun4-solaris/auto/SV
RQ/SVRQ.so: symbol PL_markstack_ptr: referenced symbol not found at /usr/local/lib/perl5/5.8.4/sun4-
solaris/DynaLoader.pm line 230.
at /usr/local/lib/perl5/site_perl/5.8.4/SXI.pm line 12
Compilation failed in require at /usr/local/lib/perl5/site_perl/5.8.4/SXI.pm line 12.
BEGIN failed--compilation aborted at /usr/local/lib/perl5/site_perl/5.8.4/SXI.pm line 12.
Compilation failed in require at /usr/local/lib/perl5/5.8.4/sxiConn.pm line 3.
BEGIN failed--compilation aborted at /usr/local/lib/perl5/5.8.4/sxiConn.pm line 3.
Compilation failed in require at sxiConn.pl line 23.
BEGIN failed--compilation aborted at sxiConn.pl line 23.
Loaded Perl file.
Executing Perl method....
Calling to Perl...
Reference miscount in sv_replace() at sxiConn.pl line 23.
Called Perl, checking values...
Uh oh - Can't load '/usr/local/lib/perl5/site_perl/5.8.4/sun4-solaris/auto/SVRQ/SVRQ.so' for module
SVRQ: ld.so.1: java: fatal: relocation error: file /usr/local/lib/perl5/site_perl/5.8.4/sun4-solaris
/auto/SVRQ/SVRQ.so: symbol PL_markstack_ptr: referenced symbol not found at /usr/local/lib/perl5/5.8
.4/sun4-solaris/DynaLoader.pm line 230.
at /usr/local/lib/perl5/site_perl/5.8.4/SXI.pm line 12
Compilation failed in require at /usr/local/lib/perl5/site_perl/5.8.4/SXI.pm line 12.
BEGIN failed--compilation aborted at /usr/local/lib/perl5/site_perl/5.8.4/SXI.pm line 12.
Compilation failed in require at /usr/local/lib/perl5/5.8.4/sxiConn.pm line 3.
BEGIN failed--compilation aborted at /usr/local/lib/perl5/5.8.4/sxiConn.pm line 3.
Compilation failed in require at sxiConn.pl line 23.
BEGIN failed--compilation aborted (in cleanup) Undefined subroutine &main::retrieveRecords cal
led at sxiConn.pl line 23.
completed call...
The problem appears to be that Java is not allowing the Perl to use external libraries. The reason we have come to this conclusion is that the C, which executes the Perl, can be executed successfully on a standalone basis. It is also worth noting that the Java can successfuly call through to Perl if there is no use of external libraries in the Perl procedure, i.e., removing the
use SXI;[\B] and subsequent calls in Perl file below.
Exerts from the Java, C and Perl procedures are shown below. Any help on this would be greatly appreciated.
Cheers
TestCall.java
[B]
package com.wibble;
public class TestCall {
// NATIVE METHOD: STUB ONLY
public native void retrieveRecords();
// LOAD LIBRARY ON STARTUP
static {
System.out.println("Loading...");
// loads the C library libnewsxiconn.so
System.loadLibrary("newsxiconn");
System.out.println("...ok");
}
public static void main(String[] args) {
TestCall myTestCall = new TestCall();
// execute the native c code
myTestCall.retrieveRecords();
}
}
newsxiconn.c
#include <EXTERN.h>
#include <perl.h>
#include <jni.h>
#include <stdio.h>
#include "com_rtel_TestCall.h"
static PerlInterpreter *my_perl;
EXTERN_C void xs_init (pTHX);
EXTERN_C void boot_Socket (pTHX_ CV* cv);
EXTERN_C void boot_DynaLoader (pTHX_ CV* cv);
EXTERN_C void
xs_init(pTHX)
{
char *file = __FILE__;
dXSUB_SYS;
newXS("Socket::bootstrap", boot_Socket, file);
/* DynaLoader is a special case */
newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
}
JNIEXPORT void JNICALL Java_com_rtel_TestCall_retrieveRecords
(JNIEnv *env, jobject obj) {
int retVal;
printf("before call...\n");
retVal = ExecuteRequests();
printf("completed call...\n");
return;
}
int ExecuteRequests()
{
/* name of the perl file we are calling */
char *my_argv[] = { "", "sxiConn.pl" };
int argc;
my_perl = perl_alloc();
perl_construct(my_perl);
printf ("Loading Perl <sxiConn.pl> file...\n") ;
perl_parse(my_perl, xs_init, argc, my_argv, NULL);
printf ("Loaded Perl file.\n") ;
printf ("Executing Perl method....\n") ;
/*** execute some perl.... ***/
call_retrieveRecords();
perl_destruct(my_perl);
perl_free(my_perl);
}
void call_retrieveRecords()
{
char * words = { "Array", "Of", "Words", "To", "Pass" };
dSP ;
int count ;
ENTER ;
SAVETMPS;
/* load temp data */
PUSHMARK(SP) ;
XPUSHs(sv_2mortal(newSVpv(words[0],0)));
XPUSHs(sv_2mortal(newSVpv(words[1],0)));
PUTBACK ;
printf ("Calling to Perl...\n") ;
count = call_pv("retrieveRecords", G_EVAL|G_ARRAY|G_KEEPERR) ;
printf ("Called Perl, checking values...\n") ;
/*refresh memory */
SPAGAIN ;
/* Check the eval first */
if (SvTRUE(ERRSV))
{
STRLEN n_a;
printf ("Uh oh - %s\n", SvPV(ERRSV, n_a)) ;
POPs ; /* clear the undfn off stack*/
}
else
{
if (count == 0)
{
croak("No values returned!, got <%d> values.\n", count) ;
}
printf ("Got <%d> values returned\n", count) ;
/* OK lets see the values! */
int i;
SV *sv;
STRLEN len;
char *str;
for (i = 1 ; i <= count ; ++i)
{
sv = POPs;
str = SvPV(sv,len);
printf ("Value %d = %s\n", i, str);
}
}
PUTBACK ;
FREETMPS ;
LEAVE ;
}
Perl file sxiConn.pl
#!/home/bin/perl
sub retrieveRecords {
use sxiConn;
my (@recordOps) = @_;
my @retVar;
my $sxiConn = new sxiConn{};
my @retVar = sxiConn->retrieveRecordsFromIN(@recordOps);
return @retVar;
}