Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

claes (1758)

claes
  (email not shown publicly)
http://www.surfar.nu/
AOL IM: claesjacobsson@mac.com (Add Buddy, Send Message)

Journal of claes (1758)

Wednesday September 05, 2001
10:23 AM

Perl - Java - Perl and stuff like that

[ #761 ]

During the last few days, i've been doing some heavy programming incorporating execution of Java code inside our Content Management System. Except the possiblity to run Perl and JavaScript in the webpages the system creates, the marketing people also wanted native Java support. At first, this sounded like an "almost" impossible task (since i had 3.5 working days to fix it). But nothing is impossible =)

Inline::Java fixes the problem to run java inside perl, but once you want java code to call perl subrutines (or methods) things get harder. So i realised it was time to dig into JNI (Java Native Interface) and mix that with perl API calls. Inline::Java is really really nice, but didn't really do what i wanted so i ended up using Jvm.pm which is just an interface to JNI Invokation Interface. We wanted to wrap our perl classes inside Java and that was the problem. This is basiclly what i ended up with:

----------------------------------------

# Wrapper Java class
public class FooWrapper {
    int _SVaddr = 0;

    static { System.loadLibrary("FooWrapper") }

    public FooWrapper(int ptr) {
        _SVaddr = ptr;
    }

    public native void printID();
}

# Some JNI code, compiles to libFooWrapper.so needed for System.loadLibrary

SV *get_sv_reflect(JNIEnv *env, jobject obj) {
    SV *reflect_sv;
    jclass class_ref;
    jfieldID addr_field_ref;
    jint addr;

    class_ref = (*env)->GetObjectClass(env, obj);
    if(!class_ref) return NULL;

    addr_field_ref = (*env)->GetFieldID(env, class_ref, "_SVaddr", "I");
    if(!addr_field_ref) return NULL;
    addr = (*env)->GetIntField(env, obj, addr_field_ref);
    if(!addr) return NULL;

    reflect_sv = (SV *) addr;
    return reflect_sv;
}

JNIEXPORT void JNICALL Java_FooWrapper_printID(JNIEnv *env, jobject obj) {
    dSP;
    SV *ref;
    ref = get_sv_reflect(env, obj);

    if(ref) {
        ENTER; SAVETMPS; PUSHMARK(SP);
        XPUSHs(ref);
        PUTBACK;

        call_pv("Foo::printID", G_VOID);

        FREETMPS;
        LEAVE;
    }
}

# Our java code
public class Party {
    public Party {
    }

    public void run(FooWrapper foo) {
        foo.printID();
    }
}

# Some perl code
package Foo;

sub new {
    my $class = shift;
    my $id = shift;

    return bless { id => $id }, $class;
}

sub printID {
    my $self = shift;
    print "ID is: $self->{id}\n"
}

package main;

use Inline ( C => "int get_sv_addr (SV *var) { return (int) var; }" );

use Jvm;

my $party = new Jvm("Party", "()V");
my $foo = new Foo(10);

my $foow = new Jvm("FooWrapper", "(I)V", get_sv_addr($foo));

$party->run("(LFooWrapper;)V", $foow);

----------------------------------------

The real code i wrote throws Java Exceptions if the perl subrutine/method dies =)

Magic =) /claes