From: Gurusamy Sarathy Date: Fri, 23 Oct 1998 21:11:56 +0000 (+0000) Subject: checkin jpl under //depot/perlext/jpl/... X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=d50cb53664b80b6874f321a43f050902c06e5781;p=p5sagit%2Fp5-mst-13.2.git checkin jpl under //depot/perlext/jpl/... p4raw-id: //depot/perlext/jpl@2041 --- d50cb53664b80b6874f321a43f050902c06e5781 diff --git a/JNI/Changes b/JNI/Changes new file mode 100644 index 0000000..dd2edf7 --- /dev/null +++ b/JNI/Changes @@ -0,0 +1,5 @@ +Revision history for Perl extension JNI. + +0.01 Wed Jun 4 13:16:03 1997 + - original version; created by h2xs 1.18 + diff --git a/JNI/JNI.pm b/JNI/JNI.pm new file mode 100644 index 0000000..b0e87af --- /dev/null +++ b/JNI/JNI.pm @@ -0,0 +1,280 @@ +package JNI; + +use strict; +use Carp; +use vars qw($VERSION @ISA @EXPORT @EXPORT_OK $AUTOLOAD $JVM @JVM_ARGS $JAVALIB); + +require Exporter; +require DynaLoader; +require AutoLoader; + +@ISA = qw(Exporter DynaLoader); + +@EXPORT = qw( + JNI_ABORT + JNI_COMMIT + JNI_ERR + JNI_FALSE + JNI_H + JNI_OK + JNI_TRUE + GetVersion + DefineClass + FindClass + GetSuperclass + IsAssignableFrom + Throw + ThrowNew + ExceptionOccurred + ExceptionDescribe + ExceptionClear + FatalError + NewGlobalRef + DeleteGlobalRef + DeleteLocalRef + IsSameObject + AllocObject + NewObject + NewObjectA + GetObjectClass + IsInstanceOf + GetMethodID + CallObjectMethod + CallObjectMethodA + CallBooleanMethod + CallBooleanMethodA + CallByteMethod + CallByteMethodA + CallCharMethod + CallCharMethodA + CallShortMethod + CallShortMethodA + CallIntMethod + CallIntMethodA + CallLongMethod + CallLongMethodA + CallFloatMethod + CallFloatMethodA + CallDoubleMethod + CallDoubleMethodA + CallVoidMethod + CallVoidMethodA + CallNonvirtualObjectMethod + CallNonvirtualObjectMethodA + CallNonvirtualBooleanMethod + CallNonvirtualBooleanMethodA + CallNonvirtualByteMethod + CallNonvirtualByteMethodA + CallNonvirtualCharMethod + CallNonvirtualCharMethodA + CallNonvirtualShortMethod + CallNonvirtualShortMethodA + CallNonvirtualIntMethod + CallNonvirtualIntMethodA + CallNonvirtualLongMethod + CallNonvirtualLongMethodA + CallNonvirtualFloatMethod + CallNonvirtualFloatMethodA + CallNonvirtualDoubleMethod + CallNonvirtualDoubleMethodA + CallNonvirtualVoidMethod + CallNonvirtualVoidMethodA + GetFieldID + GetObjectField + GetBooleanField + GetByteField + GetCharField + GetShortField + GetIntField + GetLongField + GetFloatField + GetDoubleField + SetObjectField + SetBooleanField + SetByteField + SetCharField + SetShortField + SetIntField + SetLongField + SetFloatField + SetDoubleField + GetStaticMethodID + CallStaticObjectMethod + CallStaticObjectMethodA + CallStaticBooleanMethod + CallStaticBooleanMethodA + CallStaticByteMethod + CallStaticByteMethodA + CallStaticCharMethod + CallStaticCharMethodA + CallStaticShortMethod + CallStaticShortMethodA + CallStaticIntMethod + CallStaticIntMethodA + CallStaticLongMethod + CallStaticLongMethodA + CallStaticFloatMethod + CallStaticFloatMethodA + CallStaticDoubleMethod + CallStaticDoubleMethodA + CallStaticVoidMethod + CallStaticVoidMethodA + GetStaticFieldID + GetStaticObjectField + GetStaticBooleanField + GetStaticByteField + GetStaticCharField + GetStaticShortField + GetStaticIntField + GetStaticLongField + GetStaticFloatField + GetStaticDoubleField + SetStaticObjectField + SetStaticBooleanField + SetStaticByteField + SetStaticCharField + SetStaticShortField + SetStaticIntField + SetStaticLongField + SetStaticFloatField + SetStaticDoubleField + NewString + GetStringLength + GetStringChars + NewStringUTF + GetStringUTFLength + GetStringUTFChars + GetArrayLength + NewObjectArray + GetObjectArrayElement + SetObjectArrayElement + NewBooleanArray + NewByteArray + NewCharArray + NewShortArray + NewIntArray + NewLongArray + NewFloatArray + NewDoubleArray + GetBooleanArrayElements + GetByteArrayElements + GetCharArrayElements + GetShortArrayElements + GetIntArrayElements + GetLongArrayElements + GetFloatArrayElements + GetDoubleArrayElements + GetBooleanArrayRegion + GetByteArrayRegion + GetCharArrayRegion + GetShortArrayRegion + GetIntArrayRegion + GetLongArrayRegion + GetFloatArrayRegion + GetDoubleArrayRegion + SetBooleanArrayRegion + SetByteArrayRegion + SetCharArrayRegion + SetShortArrayRegion + SetIntArrayRegion + SetLongArrayRegion + SetFloatArrayRegion + SetDoubleArrayRegion + RegisterNatives + UnregisterNatives + MonitorEnter + MonitorExit + GetJavaVM +); + +$VERSION = '0.01'; + +sub AUTOLOAD { + # This AUTOLOAD is used to 'autoload' constants from the constant() + # XS function. If a constant is not found then control is passed + # to the AUTOLOAD in AutoLoader. + + my $constname; + ($constname = $AUTOLOAD) =~ s/.*:://; + my $val = constant($constname, @_ ? $_[0] : 0); + if ($! != 0) { + if ($! =~ /Invalid/) { + $AutoLoader::AUTOLOAD = $AUTOLOAD; + goto &AutoLoader::AUTOLOAD; + } + else { + croak "Your vendor has not defined JNI macro $constname"; + } + } + eval "sub $AUTOLOAD { $val }"; + goto &$AUTOLOAD; +} + +bootstrap JNI $VERSION; + +if (not $JPL::_env_) { + $ENV{JAVA_HOME} ||= "/usr/local/java"; + + chop(my $arch = `uname -p`); + chop($arch = `uname -m`) unless -d "$ENV{JAVA_HOME}/lib/$arch"; + + my @CLASSPATH = split(/:/, $ENV{CLASSPATH}); + @CLASSPATH = "." unless @CLASSPATH; + push @CLASSPATH, + "$ENV{JAVA_HOME}/classes", + "$ENV{JAVA_HOME}/lib/classes.zip"; + $ENV{CLASSPATH} = join(':', @CLASSPATH); + + $ENV{THREADS_TYPE} ||= "green_threads"; + + $JAVALIB = "$ENV{JAVA_HOME}/lib/$arch/$ENV{THREADS_TYPE}"; + $ENV{LD_LIBRARY_PATH} .= ":$JAVALIB"; + + $JVM = GetJavaVM("$JAVALIB/libjava.so",@JVM_ARGS); +} + +# Preloaded methods go here. + +# Autoload methods go after =cut, and are processed by the autosplit program. + +1; +__END__ +# Below is the stub of documentation for your module. You better edit it! + +=head1 NAME + +JNI - Perl extension for blah blah blah + +=head1 SYNOPSIS + + use JNI; + blah blah blah + +=head1 DESCRIPTION + +Stub documentation for JNI was created by h2xs. It looks like the +author of the extension was negligent enough to leave the stub +unedited. + +Blah blah blah. + +=head1 Exported constants + + JNI_ABORT + JNI_COMMIT + JNI_ERR + JNI_FALSE + JNI_H + JNI_OK + JNI_TRUE + + +=head1 AUTHOR + +A. U. Thor, a.u.thor@a.galaxy.far.far.away + +=head1 SEE ALSO + +perl(1). + +=cut diff --git a/JNI/JNI.xs b/JNI/JNI.xs new file mode 100644 index 0000000..d54a6cc --- /dev/null +++ b/JNI/JNI.xs @@ -0,0 +1,3143 @@ +/* + * Copyright 1997, O'Reilly & Associate, Inc. + * + * This package may be copied under the same terms as Perl itself. + */ + +#ifdef __cplusplus +extern "C" { +#endif +#include "EXTERN.h" +#include "perl.h" +#include "XSUB.h" +#ifdef __cplusplus +} +#endif + +#include +#include +#include + +extern SV** stack_sp; +extern JNIEnv* jplcurenv; +extern int jpldebug; + +#define SysRet jint + +static void call_my_exit(jint status) +{ + my_exit(status); +} + +jvalue* +makeargs(char *sig, SV** svp, int items) +{ + jvalue* jv = (jvalue*)safemalloc(sizeof(jvalue) * items); + int ix = 0; + char *s = sig; + JNIEnv* env = jplcurenv; + char *start; + + if (jpldebug) + fprintf(stderr, "sig = %s, items = %d\n", sig, items); + if (*s++ != '(') + goto cleanup; + + while (items--) { + SV *sv = *svp++; + start = s; + switch (*s++) { + case 'Z': + jv[ix++].z = (jboolean)(SvIV(sv) != 0); + break; + case 'B': + jv[ix++].b = (jbyte)SvIV(sv); + break; + case 'C': + jv[ix++].c = (jchar)SvIV(sv); + break; + case 'S': + jv[ix++].s = (jshort)SvIV(sv); + break; + case 'I': + jv[ix++].i = (jint)SvIV(sv); + break; + case 'J': + jv[ix++].j = (jlong)SvNV(sv); + break; + case 'F': + jv[ix++].f = (jfloat)SvNV(sv); + break; + case 'D': + jv[ix++].d = (jdouble)SvNV(sv); + break; + case '[': + switch (*s++) { + case 'Z': + if (SvROK(sv)) { + SV* rv = (SV*)SvRV(sv); + if (SvOBJECT(rv)) + jv[ix++].l = (jobject)(void*)SvIV(rv); + else if (SvTYPE(rv) == SVt_PVAV) { + jsize len = av_len((AV*)rv) + 1; + jboolean* buf = (jboolean*)malloc(len * sizeof(jboolean)); + int i; + SV** esv; + + jbooleanArray ja = (*env)->NewBooleanArray(env, len); + for (esv = AvARRAY((AV*)rv), i = 0; i < len; esv++, i++) + buf[i] = (jboolean)SvIV(*esv); + (*env)->SetBooleanArrayRegion(env, ja, 0, len, buf); + free((void*)buf); + jv[ix++].l = (jobject)ja; + } + else + jv[ix++].l = (jobject)(void*)0; + } + else if (SvPOK(sv)) { + jsize len = sv_len(sv) / sizeof(jboolean); + + jbooleanArray ja = (*env)->NewBooleanArray(env, len); + (*env)->SetBooleanArrayRegion(env, ja, 0, len, (jboolean*)SvPV(sv,na)); + jv[ix++].l = (jobject)ja; + } + else + jv[ix++].l = (jobject)(void*)0; + break; + case 'B': + if (SvROK(sv)) { + SV* rv = (SV*)SvRV(sv); + if (SvOBJECT(rv)) + jv[ix++].l = (jobject)(void*)SvIV(rv); + else if (SvTYPE(rv) == SVt_PVAV) { + jsize len = av_len((AV*)rv) + 1; + jbyte* buf = (jbyte*)malloc(len * sizeof(jbyte)); + int i; + SV** esv; + + jbyteArray ja = (*env)->NewByteArray(env, len); + for (esv = AvARRAY((AV*)rv), i = 0; i < len; esv++, i++) + buf[i] = (jbyte)SvIV(*esv); + (*env)->SetByteArrayRegion(env, ja, 0, len, buf); + free((void*)buf); + jv[ix++].l = (jobject)ja; + } + else + jv[ix++].l = (jobject)(void*)0; + } + else if (SvPOK(sv)) { + jsize len = sv_len(sv) / sizeof(jbyte); + + jbyteArray ja = (*env)->NewByteArray(env, len); + (*env)->SetByteArrayRegion(env, ja, 0, len, (jbyte*)SvPV(sv,na)); + jv[ix++].l = (jobject)ja; + } + else + jv[ix++].l = (jobject)(void*)0; + break; + case 'C': + if (SvROK(sv)) { + SV* rv = (SV*)SvRV(sv); + if (SvOBJECT(rv)) + jv[ix++].l = (jobject)(void*)SvIV(rv); + else if (SvTYPE(rv) == SVt_PVAV) { + jsize len = av_len((AV*)rv) + 1; + jchar* buf = (jchar*)malloc(len * sizeof(jchar)); + int i; + SV** esv; + + jcharArray ja = (*env)->NewCharArray(env, len); + for (esv = AvARRAY((AV*)rv), i = 0; i < len; esv++, i++) + buf[i] = (jchar)SvIV(*esv); + (*env)->SetCharArrayRegion(env, ja, 0, len, buf); + free((void*)buf); + jv[ix++].l = (jobject)ja; + } + else + jv[ix++].l = (jobject)(void*)0; + } + else if (SvPOK(sv)) { + jsize len = sv_len(sv) / sizeof(jchar); + + jcharArray ja = (*env)->NewCharArray(env, len); + (*env)->SetCharArrayRegion(env, ja, 0, len, (jchar*)SvPV(sv,na)); + jv[ix++].l = (jobject)ja; + } + else + jv[ix++].l = (jobject)(void*)0; + break; + case 'S': + if (SvROK(sv)) { + SV* rv = (SV*)SvRV(sv); + if (SvOBJECT(rv)) + jv[ix++].l = (jobject)(void*)SvIV(rv); + else if (SvTYPE(rv) == SVt_PVAV) { + jsize len = av_len((AV*)rv) + 1; + jshort* buf = (jshort*)malloc(len * sizeof(jshort)); + int i; + SV** esv; + + jshortArray ja = (*env)->NewShortArray(env, len); + for (esv = AvARRAY((AV*)rv), i = 0; i < len; esv++, i++) + buf[i] = (jshort)SvIV(*esv); + (*env)->SetShortArrayRegion(env, ja, 0, len, buf); + free((void*)buf); + jv[ix++].l = (jobject)ja; + } + else + jv[ix++].l = (jobject)(void*)0; + } + else if (SvPOK(sv)) { + jsize len = sv_len(sv) / sizeof(jshort); + + jshortArray ja = (*env)->NewShortArray(env, len); + (*env)->SetShortArrayRegion(env, ja, 0, len, (jshort*)SvPV(sv,na)); + jv[ix++].l = (jobject)ja; + } + else + jv[ix++].l = (jobject)(void*)0; + break; + case 'I': + if (SvROK(sv)) { + SV* rv = (SV*)SvRV(sv); + if (SvOBJECT(rv)) + jv[ix++].l = (jobject)(void*)SvIV(rv); + else if (SvTYPE(rv) == SVt_PVAV) { + jsize len = av_len((AV*)rv) + 1; + jint* buf = (jint*)malloc(len * sizeof(jint)); + int i; + SV** esv; + + jintArray ja = (*env)->NewIntArray(env, len); + for (esv = AvARRAY((AV*)rv), i = 0; i < len; esv++, i++) + buf[i] = (jint)SvIV(*esv); + (*env)->SetIntArrayRegion(env, ja, 0, len, buf); + free((void*)buf); + jv[ix++].l = (jobject)ja; + } + else + jv[ix++].l = (jobject)(void*)0; + } + else if (SvPOK(sv)) { + jsize len = sv_len(sv) / sizeof(jint); + + jintArray ja = (*env)->NewIntArray(env, len); + (*env)->SetIntArrayRegion(env, ja, 0, len, (jint*)SvPV(sv,na)); + jv[ix++].l = (jobject)ja; + } + else + jv[ix++].l = (jobject)(void*)0; + break; + case 'J': + if (SvROK(sv)) { + SV* rv = (SV*)SvRV(sv); + if (SvOBJECT(rv)) + jv[ix++].l = (jobject)(void*)SvIV(rv); + else if (SvTYPE(rv) == SVt_PVAV) { + jsize len = av_len((AV*)rv) + 1; + jlong* buf = (jlong*)malloc(len * sizeof(jlong)); + int i; + SV** esv; + + jlongArray ja = (*env)->NewLongArray(env, len); + for (esv = AvARRAY((AV*)rv), i = 0; i < len; esv++, i++) + buf[i] = (jlong)SvNV(*esv); + (*env)->SetLongArrayRegion(env, ja, 0, len, buf); + free((void*)buf); + jv[ix++].l = (jobject)ja; + } + else + jv[ix++].l = (jobject)(void*)0; + } + else if (SvPOK(sv)) { + jsize len = sv_len(sv) / sizeof(jlong); + + jlongArray ja = (*env)->NewLongArray(env, len); + (*env)->SetLongArrayRegion(env, ja, 0, len, (jlong*)SvPV(sv,na)); + jv[ix++].l = (jobject)ja; + } + else + jv[ix++].l = (jobject)(void*)0; + break; + case 'F': + if (SvROK(sv)) { + SV* rv = (SV*)SvRV(sv); + if (SvOBJECT(rv)) + jv[ix++].l = (jobject)(void*)SvIV(rv); + else if (SvTYPE(rv) == SVt_PVAV) { + jsize len = av_len((AV*)rv) + 1; + jfloat* buf = (jfloat*)malloc(len * sizeof(jfloat)); + int i; + SV** esv; + + jfloatArray ja = (*env)->NewFloatArray(env, len); + for (esv = AvARRAY((AV*)rv), i = 0; i < len; esv++, i++) + buf[i] = (jfloat)SvNV(*esv); + (*env)->SetFloatArrayRegion(env, ja, 0, len, buf); + free((void*)buf); + jv[ix++].l = (jobject)ja; + } + else + jv[ix++].l = (jobject)(void*)0; + } + else if (SvPOK(sv)) { + jsize len = sv_len(sv) / sizeof(jfloat); + + jfloatArray ja = (*env)->NewFloatArray(env, len); + (*env)->SetFloatArrayRegion(env, ja, 0, len, (jfloat*)SvPV(sv,na)); + jv[ix++].l = (jobject)ja; + } + else + jv[ix++].l = (jobject)(void*)0; + break; + case 'D': + if (SvROK(sv)) { + SV* rv = (SV*)SvRV(sv); + if (SvOBJECT(rv)) + jv[ix++].l = (jobject)(void*)SvIV(rv); + else if (SvTYPE(rv) == SVt_PVAV) { + jsize len = av_len((AV*)rv) + 1; + jdouble* buf = (jdouble*)malloc(len * sizeof(jdouble)); + int i; + SV** esv; + + jdoubleArray ja = (*env)->NewDoubleArray(env, len); + for (esv = AvARRAY((AV*)rv), i = 0; i < len; esv++, i++) + buf[i] = (jdouble)SvNV(*esv); + (*env)->SetDoubleArrayRegion(env, ja, 0, len, buf); + free((void*)buf); + jv[ix++].l = (jobject)ja; + } + else + jv[ix++].l = (jobject)(void*)0; + } + else if (SvPOK(sv)) { + jsize len = sv_len(sv) / sizeof(jdouble); + + jdoubleArray ja = (*env)->NewDoubleArray(env, len); + (*env)->SetDoubleArrayRegion(env, ja, 0, len, (jdouble*)SvPV(sv,na)); + jv[ix++].l = (jobject)ja; + } + else + jv[ix++].l = (jobject)(void*)0; + break; + case 'L': + while (*s != ';') s++; + s++; + if (strnEQ(start, "[Ljava/lang/String;", 19)) { + if (SvROK(sv)) { + SV* rv = (SV*)SvRV(sv); + if (SvOBJECT(rv)) + jv[ix++].l = (jobject)(void*)SvIV(rv); + else if (SvTYPE(rv) == SVt_PVAV) { + jsize len = av_len((AV*)rv) + 1; + int i; + SV** esv; + static jclass jcl = 0; + jarray ja; + + if (!jcl) + jcl = (*env)->FindClass(env, "java/lang/String"); + ja = (*env)->NewObjectArray(env, len, jcl, 0); + for (esv = AvARRAY((AV*)rv), i = 0; i < len; esv++, i++) { + jobject str = (jobject)(*env)->NewStringUTF(env, SvPV(*esv,na)); + (*env)->SetObjectArrayElement(env, ja, i, str); + } + jv[ix++].l = (jobject)ja; + } + else + jv[ix++].l = (jobject)(void*)0; + } + else + jv[ix++].l = (jobject)(void*)0; + break; + } + /* FALL THROUGH */ + default: + if (SvROK(sv)) { + SV* rv = (SV*)SvRV(sv); + if (SvOBJECT(rv)) + jv[ix++].l = (jobject)(void*)SvIV(rv); + else if (SvTYPE(rv) == SVt_PVAV) { + jsize len = av_len((AV*)rv) + 1; + int i; + SV** esv; + static jclass jcl = 0; + jarray ja; + + if (!jcl) + jcl = (*env)->FindClass(env, "java/lang/Object"); + ja = (*env)->NewObjectArray(env, len, jcl, 0); + for (esv = AvARRAY((AV*)rv), i = 0; i < len; esv++, i++) { + if (SvROK(*esv) && (rv = SvRV(*esv)) && SvOBJECT(rv)) { + (*env)->SetObjectArrayElement(env, ja, i, + (jobject)(void*)SvIV(rv)); + } + else { + jobject str = (jobject)(*env)->NewStringUTF(env, + SvPV(*esv,na)); + (*env)->SetObjectArrayElement(env, ja, i, str); + } + } + jv[ix++].l = (jobject)ja; + } + else + jv[ix++].l = (jobject)(void*)0; + } + else + jv[ix++].l = (jobject)(void*)0; + break; + } + break; + case 'L': + if (!SvROK(sv) || strnEQ(s, "java/lang/String;", 17)) { + s += 17; + jv[ix++].l = (jobject)(*env)->NewStringUTF(env, + (char*) SvPV(sv,na)); + break; + } + while (*s != ';') s++; + s++; + if (SvROK(sv)) { + SV* rv = SvRV(sv); + jv[ix++].l = (jobject)(void*)SvIV(rv); + } + break; + case ')': + croak("too many arguments, signature: %s", sig); + goto cleanup; + default: + croak("panic: malformed signature: %s", s-1); + goto cleanup; + } + + } + if (*s != ')') { + croak("not enough arguments, signature: %s", sig); + goto cleanup; + } + return jv; + +cleanup: + safefree((char*)jv); + return 0; +} + +static int +not_here(s) +char *s; +{ + croak("%s not implemented on this architecture", s); + return -1; +} + +static double +constant(name, arg) +char *name; +int arg; +{ + errno = 0; + switch (*name) { + case 'A': + break; + case 'B': + break; + case 'C': + break; + case 'D': + break; + case 'E': + break; + case 'F': + break; + case 'G': + break; + case 'H': + break; + case 'I': + break; + case 'J': + if (strEQ(name, "JNI_ABORT")) +#ifdef JNI_ABORT + return JNI_ABORT; +#else + goto not_there; +#endif + if (strEQ(name, "JNI_COMMIT")) +#ifdef JNI_COMMIT + return JNI_COMMIT; +#else + goto not_there; +#endif + if (strEQ(name, "JNI_ERR")) +#ifdef JNI_ERR + return JNI_ERR; +#else + goto not_there; +#endif + if (strEQ(name, "JNI_FALSE")) +#ifdef JNI_FALSE + return JNI_FALSE; +#else + goto not_there; +#endif + if (strEQ(name, "JNI_H")) +#ifdef JNI_H + return JNI_H; +#else + goto not_there; +#endif + if (strEQ(name, "JNI_OK")) +#ifdef JNI_OK + return JNI_OK; +#else + goto not_there; +#endif + if (strEQ(name, "JNI_TRUE")) +#ifdef JNI_TRUE + return JNI_TRUE; +#else + goto not_there; +#endif + break; + case 'K': + break; + case 'L': + break; + case 'M': + break; + case 'N': + break; + case 'O': + break; + case 'P': + break; + case 'Q': + break; + case 'R': + break; + case 'S': + break; + case 'T': + break; + case 'U': + break; + case 'V': + break; + case 'W': + break; + case 'X': + break; + case 'Y': + break; + case 'Z': + break; + } + errno = EINVAL; + return 0; + +not_there: + errno = ENOENT; + return 0; +} + +#define FETCHENV jplcurenv +#define RESTOREENV jplcurenv = env + +MODULE = JNI PACKAGE = JNI + +PROTOTYPES: ENABLE + +double +constant(name,arg) + char * name + int arg + +jint +GetVersion() + JNIEnv * env = FETCHENV; + CODE: + { + RETVAL = (*env)->GetVersion(env); + RESTOREENV; + } + OUTPUT: + RETVAL + +jclass +DefineClass(name, loader, buf) + JNIEnv * env = FETCHENV; + STRLEN tmplen = NO_INIT; + jsize buf_len_ = NO_INIT; + const char * name + jobject loader + const jbyte * buf + CODE: + { + RETVAL = (*env)->DefineClass(env, name, loader, buf, (jsize)buf_len_); + RESTOREENV; + } + OUTPUT: + RETVAL + +jclass +FindClass(name) + JNIEnv * env = FETCHENV; + const char * name + CODE: + { + RETVAL = (*env)->FindClass(env, name); + RESTOREENV; + } + OUTPUT: + RETVAL + +jclass +GetSuperclass(sub) + JNIEnv * env = FETCHENV; + jclass sub + CODE: + { + RETVAL = (*env)->GetSuperclass(env, sub); + RESTOREENV; + } + OUTPUT: + RETVAL + +jboolean +IsAssignableFrom(sub, sup) + JNIEnv * env = FETCHENV; + jclass sub + jclass sup + CODE: + { + RETVAL = (*env)->IsAssignableFrom(env, sub, sup); + RESTOREENV; + } + OUTPUT: + RETVAL + +SysRet +Throw(obj) + JNIEnv * env = FETCHENV; + jthrowable obj + CODE: + { + RETVAL = (*env)->Throw(env, obj); + RESTOREENV; + } + OUTPUT: + RETVAL + +SysRet +ThrowNew(clazz, msg) + JNIEnv * env = FETCHENV; + jclass clazz + const char * msg + CODE: + { + RETVAL = (*env)->ThrowNew(env, clazz, msg); + RESTOREENV; + } + OUTPUT: + RETVAL + +jthrowable +ExceptionOccurred() + JNIEnv * env = FETCHENV; + CODE: + { + RETVAL = (*env)->ExceptionOccurred(env); + RESTOREENV; + } + OUTPUT: + RETVAL + +void +ExceptionDescribe() + JNIEnv * env = FETCHENV; + CODE: + { + (*env)->ExceptionDescribe(env); + RESTOREENV; + } + +void +ExceptionClear() + JNIEnv * env = FETCHENV; + CODE: + { + (*env)->ExceptionClear(env); + RESTOREENV; + } + +void +FatalError(msg) + JNIEnv * env = FETCHENV; + const char * msg + CODE: + { + (*env)->FatalError(env, msg); + RESTOREENV; + } + +jobject +NewGlobalRef(lobj) + JNIEnv * env = FETCHENV; + jobject lobj + CODE: + { + RETVAL = (*env)->NewGlobalRef(env, lobj); + RESTOREENV; + } + OUTPUT: + RETVAL + +void +DeleteGlobalRef(gref) + JNIEnv * env = FETCHENV; + jobject gref + CODE: + { + (*env)->DeleteGlobalRef(env, gref); + RESTOREENV; + } + +void +DeleteLocalRef(obj) + JNIEnv * env = FETCHENV; + jobject obj + CODE: + { + (*env)->DeleteLocalRef(env, obj); + RESTOREENV; + } + +jboolean +IsSameObject(obj1,obj2) + JNIEnv * env = FETCHENV; + jobject obj1 + jobject obj2 + CODE: + { + RETVAL = (*env)->IsSameObject(env, obj1,obj2); + RESTOREENV; + } + OUTPUT: + RETVAL + +jobject +AllocObject(clazz) + JNIEnv * env = FETCHENV; + jclass clazz + CODE: + { + RETVAL = (*env)->AllocObject(env, clazz); + RESTOREENV; + } + OUTPUT: + RETVAL + +jobject +NewObject(clazz,methodID,...) + JNIEnv * env = FETCHENV; + jclass clazz + jmethodID methodID + char * sig = 0; + int argoff = $min_args; + CODE: + { + jvalue * args = makeargs(sig, &ST(argoff), items - argoff); + RETVAL = (*env)->NewObjectA(env, clazz,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jobject +NewObjectA(clazz,methodID,args) + JNIEnv * env = FETCHENV; + jclass clazz + jmethodID methodID + char * sig = 0; + jvalue * args + CODE: + { + RETVAL = (*env)->NewObjectA(env, clazz,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jclass +GetObjectClass(obj) + JNIEnv * env = FETCHENV; + jobject obj + CODE: + { + RETVAL = (*env)->GetObjectClass(env, obj); + RESTOREENV; + } + OUTPUT: + RETVAL + +jboolean +IsInstanceOf(obj,clazz) + JNIEnv * env = FETCHENV; + jobject obj + jclass clazz + CODE: + { + RETVAL = (*env)->IsInstanceOf(env, obj,clazz); + RESTOREENV; + } + OUTPUT: + RETVAL + +jmethodID +GetMethodID(clazz,name,sig) + JNIEnv * env = FETCHENV; + jclass clazz + const char * name + const char * sig + CODE: + { + RETVAL = (*env)->GetMethodID(env, clazz,name,sig); + RESTOREENV; + } + OUTPUT: + RETVAL + +jobject +CallObjectMethod(obj,methodID,...) + JNIEnv * env = FETCHENV; + jobject obj + jmethodID methodID + char * sig = 0; + int argoff = $min_args; + CODE: + { + jvalue * args = makeargs(sig, &ST(argoff), items - argoff); + RETVAL = (*env)->CallObjectMethodA(env, obj,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jobject +CallObjectMethodA(obj,methodID,args) + JNIEnv * env = FETCHENV; + jobject obj + jmethodID methodID + char * sig = 0; + jvalue * args + CODE: + { + RETVAL = (*env)->CallObjectMethodA(env, obj,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jboolean +CallBooleanMethod(obj,methodID,...) + JNIEnv * env = FETCHENV; + jobject obj + jmethodID methodID + char * sig = 0; + int argoff = $min_args; + CODE: + { + jvalue * args = makeargs(sig, &ST(argoff), items - argoff); + RETVAL = (*env)->CallBooleanMethodA(env, obj,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jboolean +CallBooleanMethodA(obj,methodID, args) + JNIEnv * env = FETCHENV; + jobject obj + jmethodID methodID + char * sig = 0; + jvalue * args + CODE: + { + RETVAL = (*env)->CallBooleanMethodA(env, obj,methodID, args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jbyte +CallByteMethod(obj,methodID,...) + JNIEnv * env = FETCHENV; + jobject obj + jmethodID methodID + char * sig = 0; + int argoff = $min_args; + CODE: + { + jvalue * args = makeargs(sig, &ST(argoff), items - argoff); + RETVAL = (*env)->CallByteMethodA(env, obj,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jbyte +CallByteMethodA(obj,methodID,args) + JNIEnv * env = FETCHENV; + jobject obj + jmethodID methodID + char * sig = 0; + jvalue * args + CODE: + { + RETVAL = (*env)->CallByteMethodA(env, obj,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jchar +CallCharMethod(obj,methodID,...) + JNIEnv * env = FETCHENV; + jobject obj + jmethodID methodID + char * sig = 0; + int argoff = $min_args; + CODE: + { + jvalue * args = makeargs(sig, &ST(argoff), items - argoff); + RETVAL = (*env)->CallCharMethodA(env, obj,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jchar +CallCharMethodA(obj,methodID,args) + JNIEnv * env = FETCHENV; + jobject obj + jmethodID methodID + char * sig = 0; + jvalue * args + CODE: + { + RETVAL = (*env)->CallCharMethodA(env, obj,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jshort +CallShortMethod(obj,methodID,...) + JNIEnv * env = FETCHENV; + jobject obj + jmethodID methodID + char * sig = 0; + int argoff = $min_args; + CODE: + { + jvalue * args = makeargs(sig, &ST(argoff), items - argoff); + RETVAL = (*env)->CallShortMethodA(env, obj,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jshort +CallShortMethodA(obj,methodID,args) + JNIEnv * env = FETCHENV; + jobject obj + jmethodID methodID + char * sig = 0; + jvalue * args + CODE: + { + RETVAL = (*env)->CallShortMethodA(env, obj,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jint +CallIntMethod(obj,methodID,...) + JNIEnv * env = FETCHENV; + jobject obj + jmethodID methodID + char * sig = 0; + int argoff = $min_args; + CODE: + { + jvalue * args = makeargs(sig, &ST(argoff), items - argoff); + RETVAL = (*env)->CallIntMethodA(env, obj,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jint +CallIntMethodA(obj,methodID,args) + JNIEnv * env = FETCHENV; + jobject obj + jmethodID methodID + char * sig = 0; + jvalue * args + CODE: + { + RETVAL = (*env)->CallIntMethodA(env, obj,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jlong +CallLongMethod(obj,methodID,...) + JNIEnv * env = FETCHENV; + jobject obj + jmethodID methodID + char * sig = 0; + int argoff = $min_args; + CODE: + { + jvalue * args = makeargs(sig, &ST(argoff), items - argoff); + RETVAL = (*env)->CallLongMethodA(env, obj,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jlong +CallLongMethodA(obj,methodID,args) + JNIEnv * env = FETCHENV; + jobject obj + jmethodID methodID + char * sig = 0; + jvalue * args + CODE: + { + RETVAL = (*env)->CallLongMethodA(env, obj,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jfloat +CallFloatMethod(obj,methodID,...) + JNIEnv * env = FETCHENV; + jobject obj + jmethodID methodID + char * sig = 0; + int argoff = $min_args; + CODE: + { + jvalue * args = makeargs(sig, &ST(argoff), items - argoff); + RETVAL = (*env)->CallFloatMethodA(env, obj,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jfloat +CallFloatMethodA(obj,methodID,args) + JNIEnv * env = FETCHENV; + jobject obj + jmethodID methodID + char * sig = 0; + jvalue * args + CODE: + { + RETVAL = (*env)->CallFloatMethodA(env, obj,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jdouble +CallDoubleMethod(obj,methodID,...) + JNIEnv * env = FETCHENV; + jobject obj + jmethodID methodID + char * sig = 0; + int argoff = $min_args; + CODE: + { + jvalue * args = makeargs(sig, &ST(argoff), items - argoff); + RETVAL = (*env)->CallDoubleMethodA(env, obj,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jdouble +CallDoubleMethodA(obj,methodID,args) + JNIEnv * env = FETCHENV; + jobject obj + jmethodID methodID + char * sig = 0; + jvalue * args + CODE: + { + RETVAL = (*env)->CallDoubleMethodA(env, obj,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +void +CallVoidMethod(obj,methodID,...) + JNIEnv * env = FETCHENV; + jobject obj + jmethodID methodID + char * sig = 0; + int argoff = $min_args; + CODE: + { + jvalue * args = makeargs(sig, &ST(argoff), items - argoff); + (*env)->CallVoidMethodA(env, obj,methodID,args); + RESTOREENV; + } + +void +CallVoidMethodA(obj,methodID,args) + JNIEnv * env = FETCHENV; + jobject obj + jmethodID methodID + char * sig = 0; + jvalue * args + CODE: + { + (*env)->CallVoidMethodA(env, obj,methodID,args); + RESTOREENV; + } + +jobject +CallNonvirtualObjectMethod(obj,clazz,methodID,...) + JNIEnv * env = FETCHENV; + jobject obj + jclass clazz + jmethodID methodID + char * sig = 0; + int argoff = $min_args; + CODE: + { + jvalue * args = makeargs(sig, &ST(argoff), items - argoff); + RETVAL = (*env)->CallNonvirtualObjectMethodA(env, obj,clazz,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jobject +CallNonvirtualObjectMethodA(obj,clazz,methodID,args) + JNIEnv * env = FETCHENV; + jobject obj + jclass clazz + jmethodID methodID + char * sig = 0; + jvalue * args + CODE: + { + RETVAL = (*env)->CallNonvirtualObjectMethodA(env, obj,clazz,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jboolean +CallNonvirtualBooleanMethod(obj,clazz,methodID,...) + JNIEnv * env = FETCHENV; + jobject obj + jclass clazz + jmethodID methodID + char * sig = 0; + int argoff = $min_args; + CODE: + { + jvalue * args = makeargs(sig, &ST(argoff), items - argoff); + RETVAL = (*env)->CallNonvirtualBooleanMethodA(env, obj,clazz,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jboolean +CallNonvirtualBooleanMethodA(obj,clazz,methodID, args) + JNIEnv * env = FETCHENV; + jobject obj + jclass clazz + jmethodID methodID + char * sig = 0; + jvalue * args + CODE: + { + RETVAL = (*env)->CallNonvirtualBooleanMethodA(env, obj,clazz,methodID, args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jbyte +CallNonvirtualByteMethod(obj,clazz,methodID,...) + JNIEnv * env = FETCHENV; + jobject obj + jclass clazz + jmethodID methodID + char * sig = 0; + int argoff = $min_args; + CODE: + { + jvalue * args = makeargs(sig, &ST(argoff), items - argoff); + RETVAL = (*env)->CallNonvirtualByteMethodA(env, obj,clazz,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jbyte +CallNonvirtualByteMethodA(obj,clazz,methodID,args) + JNIEnv * env = FETCHENV; + jobject obj + jclass clazz + jmethodID methodID + char * sig = 0; + jvalue * args + CODE: + { + RETVAL = (*env)->CallNonvirtualByteMethodA(env, obj,clazz,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jchar +CallNonvirtualCharMethod(obj,clazz,methodID,...) + JNIEnv * env = FETCHENV; + jobject obj + jclass clazz + jmethodID methodID + char * sig = 0; + int argoff = $min_args; + CODE: + { + jvalue * args = makeargs(sig, &ST(argoff), items - argoff); + RETVAL = (*env)->CallNonvirtualCharMethodA(env, obj,clazz,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jchar +CallNonvirtualCharMethodA(obj,clazz,methodID,args) + JNIEnv * env = FETCHENV; + jobject obj + jclass clazz + jmethodID methodID + char * sig = 0; + jvalue * args + CODE: + { + RETVAL = (*env)->CallNonvirtualCharMethodA(env, obj,clazz,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jshort +CallNonvirtualShortMethod(obj,clazz,methodID,...) + JNIEnv * env = FETCHENV; + jobject obj + jclass clazz + jmethodID methodID + char * sig = 0; + int argoff = $min_args; + CODE: + { + jvalue * args = makeargs(sig, &ST(argoff), items - argoff); + RETVAL = (*env)->CallNonvirtualShortMethodA(env, obj,clazz,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jshort +CallNonvirtualShortMethodA(obj,clazz,methodID,args) + JNIEnv * env = FETCHENV; + jobject obj + jclass clazz + jmethodID methodID + char * sig = 0; + jvalue * args + CODE: + { + RETVAL = (*env)->CallNonvirtualShortMethodA(env, obj,clazz,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jint +CallNonvirtualIntMethod(obj,clazz,methodID,...) + JNIEnv * env = FETCHENV; + jobject obj + jclass clazz + jmethodID methodID + char * sig = 0; + int argoff = $min_args; + CODE: + { + jvalue * args = makeargs(sig, &ST(argoff), items - argoff); + RETVAL = (*env)->CallNonvirtualIntMethodA(env, obj,clazz,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jint +CallNonvirtualIntMethodA(obj,clazz,methodID,args) + JNIEnv * env = FETCHENV; + jobject obj + jclass clazz + jmethodID methodID + char * sig = 0; + jvalue * args + CODE: + { + RETVAL = (*env)->CallNonvirtualIntMethodA(env, obj,clazz,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jlong +CallNonvirtualLongMethod(obj,clazz,methodID,...) + JNIEnv * env = FETCHENV; + jobject obj + jclass clazz + jmethodID methodID + char * sig = 0; + int argoff = $min_args; + CODE: + { + jvalue * args = makeargs(sig, &ST(argoff), items - argoff); + RETVAL = (*env)->CallNonvirtualLongMethodA(env, obj,clazz,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jlong +CallNonvirtualLongMethodA(obj,clazz,methodID,args) + JNIEnv * env = FETCHENV; + jobject obj + jclass clazz + jmethodID methodID + char * sig = 0; + jvalue * args + CODE: + { + RETVAL = (*env)->CallNonvirtualLongMethodA(env, obj,clazz,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jfloat +CallNonvirtualFloatMethod(obj,clazz,methodID,...) + JNIEnv * env = FETCHENV; + jobject obj + jclass clazz + jmethodID methodID + char * sig = 0; + int argoff = $min_args; + CODE: + { + jvalue * args = makeargs(sig, &ST(argoff), items - argoff); + RETVAL = (*env)->CallNonvirtualFloatMethodA(env, obj,clazz,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jfloat +CallNonvirtualFloatMethodA(obj,clazz,methodID,args) + JNIEnv * env = FETCHENV; + jobject obj + jclass clazz + jmethodID methodID + char * sig = 0; + jvalue * args + CODE: + { + RETVAL = (*env)->CallNonvirtualFloatMethodA(env, obj,clazz,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jdouble +CallNonvirtualDoubleMethod(obj,clazz,methodID,...) + JNIEnv * env = FETCHENV; + jobject obj + jclass clazz + jmethodID methodID + char * sig = 0; + int argoff = $min_args; + CODE: + { + jvalue * args = makeargs(sig, &ST(argoff), items - argoff); + RETVAL = (*env)->CallNonvirtualDoubleMethodA(env, obj,clazz,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jdouble +CallNonvirtualDoubleMethodA(obj,clazz,methodID,args) + JNIEnv * env = FETCHENV; + jobject obj + jclass clazz + jmethodID methodID + char * sig = 0; + jvalue * args + CODE: + { + RETVAL = (*env)->CallNonvirtualDoubleMethodA(env, obj,clazz,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +void +CallNonvirtualVoidMethod(obj,clazz,methodID,...) + JNIEnv * env = FETCHENV; + jobject obj + jclass clazz + jmethodID methodID + char * sig = 0; + int argoff = $min_args; + CODE: + { + jvalue * args = makeargs(sig, &ST(argoff), items - argoff); + (*env)->CallNonvirtualVoidMethodA(env, obj,clazz,methodID,args); + RESTOREENV; + } + +void +CallNonvirtualVoidMethodA(obj,clazz,methodID,args) + JNIEnv * env = FETCHENV; + jobject obj + jclass clazz + jmethodID methodID + char * sig = 0; + jvalue * args + CODE: + { + (*env)->CallNonvirtualVoidMethodA(env, obj,clazz,methodID,args); + RESTOREENV; + } + +jfieldID +GetFieldID(clazz,name,sig) + JNIEnv * env = FETCHENV; + jclass clazz + const char * name + const char * sig + CODE: + { + RETVAL = (*env)->GetFieldID(env, clazz,name,sig); + RESTOREENV; + } + OUTPUT: + RETVAL + +jobject +GetObjectField(obj,fieldID) + JNIEnv * env = FETCHENV; + jobject obj + jfieldID fieldID + char * sig = 0; + CODE: + { + RETVAL = (*env)->GetObjectField(env, obj,fieldID); + RESTOREENV; + } + OUTPUT: + RETVAL + +jboolean +GetBooleanField(obj,fieldID) + JNIEnv * env = FETCHENV; + jobject obj + jfieldID fieldID + char * sig = 0; + CODE: + { + RETVAL = (*env)->GetBooleanField(env, obj,fieldID); + RESTOREENV; + } + OUTPUT: + RETVAL + +jbyte +GetByteField(obj,fieldID) + JNIEnv * env = FETCHENV; + jobject obj + jfieldID fieldID + char * sig = 0; + CODE: + { + RETVAL = (*env)->GetByteField(env, obj,fieldID); + RESTOREENV; + } + OUTPUT: + RETVAL + +jchar +GetCharField(obj,fieldID) + JNIEnv * env = FETCHENV; + jobject obj + jfieldID fieldID + char * sig = 0; + CODE: + { + RETVAL = (*env)->GetCharField(env, obj,fieldID); + RESTOREENV; + } + OUTPUT: + RETVAL + +jshort +GetShortField(obj,fieldID) + JNIEnv * env = FETCHENV; + jobject obj + jfieldID fieldID + char * sig = 0; + CODE: + { + RETVAL = (*env)->GetShortField(env, obj,fieldID); + RESTOREENV; + } + OUTPUT: + RETVAL + +jint +GetIntField(obj,fieldID) + JNIEnv * env = FETCHENV; + jobject obj + jfieldID fieldID + char * sig = 0; + CODE: + { + RETVAL = (*env)->GetIntField(env, obj,fieldID); + RESTOREENV; + } + OUTPUT: + RETVAL + +jlong +GetLongField(obj,fieldID) + JNIEnv * env = FETCHENV; + jobject obj + jfieldID fieldID + char * sig = 0; + CODE: + { + RETVAL = (*env)->GetLongField(env, obj,fieldID); + RESTOREENV; + } + OUTPUT: + RETVAL + +jfloat +GetFloatField(obj,fieldID) + JNIEnv * env = FETCHENV; + jobject obj + jfieldID fieldID + char * sig = 0; + CODE: + { + RETVAL = (*env)->GetFloatField(env, obj,fieldID); + RESTOREENV; + } + OUTPUT: + RETVAL + +jdouble +GetDoubleField(obj,fieldID) + JNIEnv * env = FETCHENV; + jobject obj + jfieldID fieldID + char * sig = 0; + CODE: + { + RETVAL = (*env)->GetDoubleField(env, obj,fieldID); + RESTOREENV; + } + OUTPUT: + RETVAL + +void +SetObjectField(obj,fieldID,val) + JNIEnv * env = FETCHENV; + jobject obj + jfieldID fieldID + char * sig = 0; + jobject val + CODE: + { + (*env)->SetObjectField(env, obj,fieldID,val); + RESTOREENV; + } + +void +SetBooleanField(obj,fieldID,val) + JNIEnv * env = FETCHENV; + jobject obj + jfieldID fieldID + char * sig = 0; + jboolean val + CODE: + { + (*env)->SetBooleanField(env, obj,fieldID,val); + RESTOREENV; + } + +void +SetByteField(obj,fieldID,val) + JNIEnv * env = FETCHENV; + jobject obj + jfieldID fieldID + char * sig = 0; + jbyte val + CODE: + { + (*env)->SetByteField(env, obj,fieldID,val); + RESTOREENV; + } + +void +SetCharField(obj,fieldID,val) + JNIEnv * env = FETCHENV; + jobject obj + jfieldID fieldID + char * sig = 0; + jchar val + CODE: + { + (*env)->SetCharField(env, obj,fieldID,val); + RESTOREENV; + } + +void +SetShortField(obj,fieldID,val) + JNIEnv * env = FETCHENV; + jobject obj + jfieldID fieldID + char * sig = 0; + jshort val + CODE: + { + (*env)->SetShortField(env, obj,fieldID,val); + RESTOREENV; + } + +void +SetIntField(obj,fieldID,val) + JNIEnv * env = FETCHENV; + jobject obj + jfieldID fieldID + char * sig = 0; + jint val + CODE: + { + (*env)->SetIntField(env, obj,fieldID,val); + RESTOREENV; + } + +void +SetLongField(obj,fieldID,val) + JNIEnv * env = FETCHENV; + jobject obj + jfieldID fieldID + char * sig = 0; + jlong val + CODE: + { + (*env)->SetLongField(env, obj,fieldID,val); + RESTOREENV; + } + +void +SetFloatField(obj,fieldID,val) + JNIEnv * env = FETCHENV; + jobject obj + jfieldID fieldID + char * sig = 0; + jfloat val + CODE: + { + (*env)->SetFloatField(env, obj,fieldID,val); + RESTOREENV; + } + +void +SetDoubleField(obj,fieldID,val) + JNIEnv * env = FETCHENV; + jobject obj + jfieldID fieldID + char * sig = 0; + jdouble val + CODE: + { + (*env)->SetDoubleField(env, obj,fieldID,val); + RESTOREENV; + } + +jmethodID +GetStaticMethodID(clazz,name,sig) + JNIEnv * env = FETCHENV; + jclass clazz + const char * name + const char * sig + CODE: + { + RETVAL = (*env)->GetStaticMethodID(env, clazz,name,sig); + RESTOREENV; + } + OUTPUT: + RETVAL + +jobject +CallStaticObjectMethod(clazz,methodID,...) + JNIEnv * env = FETCHENV; + jclass clazz + jmethodID methodID + char * sig = 0; + int argoff = $min_args; + CODE: + { + jvalue * args = makeargs(sig, &ST(argoff), items - argoff); + RETVAL = (*env)->CallStaticObjectMethodA(env, clazz,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jobject +CallStaticObjectMethodA(clazz,methodID,args) + JNIEnv * env = FETCHENV; + jclass clazz + jmethodID methodID + char * sig = 0; + jvalue * args + CODE: + { + RETVAL = (*env)->CallStaticObjectMethodA(env, clazz,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jboolean +CallStaticBooleanMethod(clazz,methodID,...) + JNIEnv * env = FETCHENV; + jclass clazz + jmethodID methodID + char * sig = 0; + int argoff = $min_args; + CODE: + { + jvalue * args = makeargs(sig, &ST(argoff), items - argoff); + RETVAL = (*env)->CallStaticBooleanMethodA(env, clazz,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jboolean +CallStaticBooleanMethodA(clazz,methodID,args) + JNIEnv * env = FETCHENV; + jclass clazz + jmethodID methodID + char * sig = 0; + jvalue * args + CODE: + { + RETVAL = (*env)->CallStaticBooleanMethodA(env, clazz,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jbyte +CallStaticByteMethod(clazz,methodID,...) + JNIEnv * env = FETCHENV; + jclass clazz + jmethodID methodID + char * sig = 0; + int argoff = $min_args; + CODE: + { + jvalue * args = makeargs(sig, &ST(argoff), items - argoff); + RETVAL = (*env)->CallStaticByteMethodA(env, clazz,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jbyte +CallStaticByteMethodA(clazz,methodID,args) + JNIEnv * env = FETCHENV; + jclass clazz + jmethodID methodID + char * sig = 0; + jvalue * args + CODE: + { + RETVAL = (*env)->CallStaticByteMethodA(env, clazz,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jchar +CallStaticCharMethod(clazz,methodID,...) + JNIEnv * env = FETCHENV; + jclass clazz + jmethodID methodID + char * sig = 0; + int argoff = $min_args; + CODE: + { + jvalue * args = makeargs(sig, &ST(argoff), items - argoff); + RETVAL = (*env)->CallStaticCharMethodA(env, clazz,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jchar +CallStaticCharMethodA(clazz,methodID,args) + JNIEnv * env = FETCHENV; + jclass clazz + jmethodID methodID + char * sig = 0; + jvalue * args + CODE: + { + RETVAL = (*env)->CallStaticCharMethodA(env, clazz,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jshort +CallStaticShortMethod(clazz,methodID,...) + JNIEnv * env = FETCHENV; + jclass clazz + jmethodID methodID + char * sig = 0; + int argoff = $min_args; + CODE: + { + jvalue * args = makeargs(sig, &ST(argoff), items - argoff); + RETVAL = (*env)->CallStaticShortMethodA(env, clazz,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jshort +CallStaticShortMethodA(clazz,methodID,args) + JNIEnv * env = FETCHENV; + jclass clazz + jmethodID methodID + char * sig = 0; + jvalue * args + CODE: + { + RETVAL = (*env)->CallStaticShortMethodA(env, clazz,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jint +CallStaticIntMethod(clazz,methodID,...) + JNIEnv * env = FETCHENV; + jclass clazz + jmethodID methodID + char * sig = 0; + int argoff = $min_args; + CODE: + { + jvalue * args = makeargs(sig, &ST(argoff), items - argoff); + RETVAL = (*env)->CallStaticIntMethodA(env, clazz,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jint +CallStaticIntMethodA(clazz,methodID,args) + JNIEnv * env = FETCHENV; + jclass clazz + jmethodID methodID + char * sig = 0; + jvalue * args + CODE: + { + RETVAL = (*env)->CallStaticIntMethodA(env, clazz,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jlong +CallStaticLongMethod(clazz,methodID,...) + JNIEnv * env = FETCHENV; + jclass clazz + jmethodID methodID + char * sig = 0; + int argoff = $min_args; + CODE: + { + jvalue * args = makeargs(sig, &ST(argoff), items - argoff); + RETVAL = (*env)->CallStaticLongMethodA(env, clazz,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jlong +CallStaticLongMethodA(clazz,methodID,args) + JNIEnv * env = FETCHENV; + jclass clazz + jmethodID methodID + char * sig = 0; + jvalue * args + CODE: + { + RETVAL = (*env)->CallStaticLongMethodA(env, clazz,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jfloat +CallStaticFloatMethod(clazz,methodID,...) + JNIEnv * env = FETCHENV; + jclass clazz + jmethodID methodID + char * sig = 0; + int argoff = $min_args; + CODE: + { + jvalue * args = makeargs(sig, &ST(argoff), items - argoff); + RETVAL = (*env)->CallStaticFloatMethodA(env, clazz,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jfloat +CallStaticFloatMethodA(clazz,methodID,args) + JNIEnv * env = FETCHENV; + jclass clazz + jmethodID methodID + char * sig = 0; + jvalue * args + CODE: + { + RETVAL = (*env)->CallStaticFloatMethodA(env, clazz,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jdouble +CallStaticDoubleMethod(clazz,methodID,...) + JNIEnv * env = FETCHENV; + jclass clazz + jmethodID methodID + char * sig = 0; + int argoff = $min_args; + CODE: + { + jvalue * args = makeargs(sig, &ST(argoff), items - argoff); + RETVAL = (*env)->CallStaticDoubleMethodA(env, clazz,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +jdouble +CallStaticDoubleMethodA(clazz,methodID,args) + JNIEnv * env = FETCHENV; + jclass clazz + jmethodID methodID + char * sig = 0; + jvalue * args + CODE: + { + RETVAL = (*env)->CallStaticDoubleMethodA(env, clazz,methodID,args); + RESTOREENV; + } + OUTPUT: + RETVAL + +void +CallStaticVoidMethod(cls,methodID,...) + JNIEnv * env = FETCHENV; + jclass cls + jmethodID methodID + char * sig = 0; + int argoff = $min_args; + CODE: + { + jvalue * args = makeargs(sig, &ST(argoff), items - argoff); + (*env)->CallStaticVoidMethodA(env, cls,methodID,args); + RESTOREENV; + } + +void +CallStaticVoidMethodA(cls,methodID,args) + JNIEnv * env = FETCHENV; + jclass cls + jmethodID methodID + char * sig = 0; + jvalue * args + CODE: + { + (*env)->CallStaticVoidMethodA(env, cls,methodID,args); + RESTOREENV; + } + +jfieldID +GetStaticFieldID(clazz,name,sig) + JNIEnv * env = FETCHENV; + jclass clazz + const char * name + const char * sig + CODE: + { + RETVAL = (*env)->GetStaticFieldID(env, clazz,name,sig); + RESTOREENV; + } + OUTPUT: + RETVAL + +jobject +GetStaticObjectField(clazz,fieldID) + JNIEnv * env = FETCHENV; + jclass clazz + jfieldID fieldID + char * sig = 0; + CODE: + { + RETVAL = (*env)->GetStaticObjectField(env, clazz,fieldID); + RESTOREENV; + } + OUTPUT: + RETVAL + +jboolean +GetStaticBooleanField(clazz,fieldID) + JNIEnv * env = FETCHENV; + jclass clazz + jfieldID fieldID + char * sig = 0; + CODE: + { + RETVAL = (*env)->GetStaticBooleanField(env, clazz,fieldID); + RESTOREENV; + } + OUTPUT: + RETVAL + +jbyte +GetStaticByteField(clazz,fieldID) + JNIEnv * env = FETCHENV; + jclass clazz + jfieldID fieldID + char * sig = 0; + CODE: + { + RETVAL = (*env)->GetStaticByteField(env, clazz,fieldID); + RESTOREENV; + } + OUTPUT: + RETVAL + +jchar +GetStaticCharField(clazz,fieldID) + JNIEnv * env = FETCHENV; + jclass clazz + jfieldID fieldID + char * sig = 0; + CODE: + { + RETVAL = (*env)->GetStaticCharField(env, clazz,fieldID); + RESTOREENV; + } + OUTPUT: + RETVAL + +jshort +GetStaticShortField(clazz,fieldID) + JNIEnv * env = FETCHENV; + jclass clazz + jfieldID fieldID + char * sig = 0; + CODE: + { + RETVAL = (*env)->GetStaticShortField(env, clazz,fieldID); + RESTOREENV; + } + OUTPUT: + RETVAL + +jint +GetStaticIntField(clazz,fieldID) + JNIEnv * env = FETCHENV; + jclass clazz + jfieldID fieldID + char * sig = 0; + CODE: + { + RETVAL = (*env)->GetStaticIntField(env, clazz,fieldID); + RESTOREENV; + } + OUTPUT: + RETVAL + +jlong +GetStaticLongField(clazz,fieldID) + JNIEnv * env = FETCHENV; + jclass clazz + jfieldID fieldID + char * sig = 0; + CODE: + { + RETVAL = (*env)->GetStaticLongField(env, clazz,fieldID); + RESTOREENV; + } + OUTPUT: + RETVAL + +jfloat +GetStaticFloatField(clazz,fieldID) + JNIEnv * env = FETCHENV; + jclass clazz + jfieldID fieldID + char * sig = 0; + CODE: + { + RETVAL = (*env)->GetStaticFloatField(env, clazz,fieldID); + RESTOREENV; + } + OUTPUT: + RETVAL + +jdouble +GetStaticDoubleField(clazz,fieldID) + JNIEnv * env = FETCHENV; + jclass clazz + jfieldID fieldID + char * sig = 0; + CODE: + { + RETVAL = (*env)->GetStaticDoubleField(env, clazz,fieldID); + RESTOREENV; + } + OUTPUT: + RETVAL + +void +SetStaticObjectField(clazz,fieldID,value) + JNIEnv * env = FETCHENV; + jclass clazz + jfieldID fieldID + char * sig = 0; + jobject value + CODE: + { + (*env)->SetStaticObjectField(env, clazz,fieldID,value); + RESTOREENV; + } + +void +SetStaticBooleanField(clazz,fieldID,value) + JNIEnv * env = FETCHENV; + jclass clazz + jfieldID fieldID + char * sig = 0; + jboolean value + CODE: + { + (*env)->SetStaticBooleanField(env, clazz,fieldID,value); + RESTOREENV; + } + +void +SetStaticByteField(clazz,fieldID,value) + JNIEnv * env = FETCHENV; + jclass clazz + jfieldID fieldID + char * sig = 0; + jbyte value + CODE: + { + (*env)->SetStaticByteField(env, clazz,fieldID,value); + RESTOREENV; + } + +void +SetStaticCharField(clazz,fieldID,value) + JNIEnv * env = FETCHENV; + jclass clazz + jfieldID fieldID + char * sig = 0; + jchar value + CODE: + { + (*env)->SetStaticCharField(env, clazz,fieldID,value); + RESTOREENV; + } + +void +SetStaticShortField(clazz,fieldID,value) + JNIEnv * env = FETCHENV; + jclass clazz + jfieldID fieldID + char * sig = 0; + jshort value + CODE: + { + (*env)->SetStaticShortField(env, clazz,fieldID,value); + RESTOREENV; + } + +void +SetStaticIntField(clazz,fieldID,value) + JNIEnv * env = FETCHENV; + jclass clazz + jfieldID fieldID + char * sig = 0; + jint value + CODE: + { + (*env)->SetStaticIntField(env, clazz,fieldID,value); + RESTOREENV; + } + +void +SetStaticLongField(clazz,fieldID,value) + JNIEnv * env = FETCHENV; + jclass clazz + jfieldID fieldID + char * sig = 0; + jlong value + CODE: + { + (*env)->SetStaticLongField(env, clazz,fieldID,value); + RESTOREENV; + } + +void +SetStaticFloatField(clazz,fieldID,value) + JNIEnv * env = FETCHENV; + jclass clazz + jfieldID fieldID + char * sig = 0; + jfloat value + CODE: + { + (*env)->SetStaticFloatField(env, clazz,fieldID,value); + RESTOREENV; + } + +void +SetStaticDoubleField(clazz,fieldID,value) + JNIEnv * env = FETCHENV; + jclass clazz + jfieldID fieldID + char * sig = 0; + jdouble value + CODE: + { + (*env)->SetStaticDoubleField(env, clazz,fieldID,value); + RESTOREENV; + } + +jstring +NewString(unicode) + JNIEnv * env = FETCHENV; + STRLEN tmplen = NO_INIT; + jsize unicode_len_ = NO_INIT; + const jchar * unicode + CODE: + { + RETVAL = (*env)->NewString(env, unicode, unicode_len_); + RESTOREENV; + } + OUTPUT: + RETVAL + +jsize +GetStringLength(str) + JNIEnv * env = FETCHENV; + jstring str + CODE: + { + RETVAL = (*env)->GetStringLength(env, str); + RESTOREENV; + } + OUTPUT: + RETVAL + +const jchar * +GetStringChars(str) + JNIEnv * env = FETCHENV; + jstring str + jboolean isCopy = NO_INIT; + jsize RETVAL_len_ = NO_INIT; + CODE: + { + RETVAL = (*env)->GetStringChars(env, str,&isCopy); + RETVAL_len_ = (*env)->GetStringLength(env, str); + RESTOREENV; + } + OUTPUT: + RETVAL + CLEANUP: + (*env)->ReleaseStringChars(env, str,RETVAL); + +jstring +NewStringUTF(utf) + JNIEnv * env = FETCHENV; + const char * utf + CODE: + { + RETVAL = (*env)->NewStringUTF(env, utf); + RESTOREENV; + } + OUTPUT: + RETVAL + +jsize +GetStringUTFLength(str) + JNIEnv * env = FETCHENV; + jstring str + CODE: + { + RETVAL = (*env)->GetStringUTFLength(env, str); + RESTOREENV; + } + OUTPUT: + RETVAL + +const char * +GetStringUTFChars(str) + JNIEnv * env = FETCHENV; + jstring str + jboolean isCopy = NO_INIT; + CODE: + { + RETVAL = (*env)->GetStringUTFChars(env, str,&isCopy); + RESTOREENV; + } + OUTPUT: + RETVAL + CLEANUP: + (*env)->ReleaseStringUTFChars(env, str, RETVAL); + + +jsize +GetArrayLength(array) + JNIEnv * env = FETCHENV; + jarray array + CODE: + { + RETVAL = (*env)->GetArrayLength(env, array); + RESTOREENV; + } + OUTPUT: + RETVAL + +jobjectArray +NewObjectArray(len,clazz,init) + JNIEnv * env = FETCHENV; + jsize len + jclass clazz + jobject init + CODE: + { + RETVAL = (*env)->NewObjectArray(env, len,clazz,init); + RESTOREENV; + } + OUTPUT: + RETVAL + +jobject +GetObjectArrayElement(array,index) + JNIEnv * env = FETCHENV; + jobjectArray array + jsize index + CODE: + { + RETVAL = (*env)->GetObjectArrayElement(env, array,index); + RESTOREENV; + } + OUTPUT: + RETVAL + +void +SetObjectArrayElement(array,index,val) + JNIEnv * env = FETCHENV; + jobjectArray array + jsize index + jobject val + CODE: + { + (*env)->SetObjectArrayElement(env, array,index,val); + RESTOREENV; + } + +jbooleanArray +NewBooleanArray(len) + JNIEnv * env = FETCHENV; + jsize len + CODE: + { + RETVAL = (*env)->NewBooleanArray(env, len); + RESTOREENV; + } + OUTPUT: + RETVAL + +jbyteArray +NewByteArray(len) + JNIEnv * env = FETCHENV; + jsize len + CODE: + { + RETVAL = (*env)->NewByteArray(env, len); + RESTOREENV; + } + OUTPUT: + RETVAL + +jcharArray +NewCharArray(len) + JNIEnv * env = FETCHENV; + jsize len + CODE: + { + RETVAL = (*env)->NewCharArray(env, len); + RESTOREENV; + } + OUTPUT: + RETVAL + +jshortArray +NewShortArray(len) + JNIEnv * env = FETCHENV; + jsize len + CODE: + { + RETVAL = (*env)->NewShortArray(env, len); + RESTOREENV; + } + OUTPUT: + RETVAL + +jintArray +NewIntArray(len) + JNIEnv * env = FETCHENV; + jsize len + CODE: + { + RETVAL = (*env)->NewIntArray(env, len); + RESTOREENV; + } + OUTPUT: + RETVAL + +jlongArray +NewLongArray(len) + JNIEnv * env = FETCHENV; + jsize len + CODE: + { + RETVAL = (*env)->NewLongArray(env, len); + RESTOREENV; + } + OUTPUT: + RETVAL + +jfloatArray +NewFloatArray(len) + JNIEnv * env = FETCHENV; + jsize len + CODE: + { + RETVAL = (*env)->NewFloatArray(env, len); + RESTOREENV; + } + OUTPUT: + RETVAL + +jdoubleArray +NewDoubleArray(len) + JNIEnv * env = FETCHENV; + jsize len + CODE: + { + RETVAL = (*env)->NewDoubleArray(env, len); + RESTOREENV; + } + OUTPUT: + RETVAL + +jboolean * +GetBooleanArrayElements(array) + JNIEnv * env = FETCHENV; + jsize RETVAL_len_ = NO_INIT; + jbooleanArray array + jboolean isCopy = NO_INIT; + PPCODE: + { + RETVAL = (*env)->GetBooleanArrayElements(env, array,&isCopy); + RETVAL_len_ = (*env)->GetArrayLength(env, array); + if (GIMME == G_ARRAY) { + int i; + jboolean* r = RETVAL; + EXTEND(sp, RETVAL_len_); + for (i = RETVAL_len_; i; --i) { + PUSHs(sv_2mortal(newSViv(*r++))); + } + } + else { + if (RETVAL_len_) { + PUSHs(sv_2mortal(newSVpv((char*)RETVAL, + (STRLEN)RETVAL_len_ * sizeof(jboolean)))); + } + else + PUSHs(&sv_no); + } + (*env)->ReleaseBooleanArrayElements(env, array,RETVAL,JNI_ABORT); + RESTOREENV; + } + +jbyte * +GetByteArrayElements(array) + JNIEnv * env = FETCHENV; + jsize RETVAL_len_ = NO_INIT; + jbyteArray array + jboolean isCopy = NO_INIT; + PPCODE: + { + RETVAL = (*env)->GetByteArrayElements(env, array,&isCopy); + RETVAL_len_ = (*env)->GetArrayLength(env, array); + if (GIMME == G_ARRAY) { + int i; + jbyte* r = RETVAL; + EXTEND(sp, RETVAL_len_); + for (i = RETVAL_len_; i; --i) { + PUSHs(sv_2mortal(newSViv(*r++))); + } + } + else { + if (RETVAL_len_) { + PUSHs(sv_2mortal(newSVpv((char*)RETVAL, + (STRLEN)RETVAL_len_ * sizeof(jbyte)))); + } + else + PUSHs(&sv_no); + } + (*env)->ReleaseByteArrayElements(env, array,RETVAL,JNI_ABORT); + RESTOREENV; + } + +jchar * +GetCharArrayElements(array) + JNIEnv * env = FETCHENV; + jsize RETVAL_len_ = NO_INIT; + jcharArray array + jboolean isCopy = NO_INIT; + PPCODE: + { + RETVAL = (*env)->GetCharArrayElements(env, array,&isCopy); + RETVAL_len_ = (*env)->GetArrayLength(env, array); + if (GIMME == G_ARRAY) { + int i; + jchar* r = RETVAL; + EXTEND(sp, RETVAL_len_); + for (i = RETVAL_len_; i; --i) { + PUSHs(sv_2mortal(newSViv(*r++))); + } + } + else { + if (RETVAL_len_) { + PUSHs(sv_2mortal(newSVpv((char*)RETVAL, + (STRLEN)RETVAL_len_ * sizeof(jchar)))); + } + else + PUSHs(&sv_no); + } + (*env)->ReleaseCharArrayElements(env, array,RETVAL,JNI_ABORT); + RESTOREENV; + } + +jshort * +GetShortArrayElements(array) + JNIEnv * env = FETCHENV; + jsize RETVAL_len_ = NO_INIT; + jshortArray array + jboolean isCopy = NO_INIT; + PPCODE: + { + RETVAL = (*env)->GetShortArrayElements(env, array,&isCopy); + RETVAL_len_ = (*env)->GetArrayLength(env, array); + if (GIMME == G_ARRAY) { + int i; + jshort* r = RETVAL; + EXTEND(sp, RETVAL_len_); + for (i = RETVAL_len_; i; --i) { + PUSHs(sv_2mortal(newSViv(*r++))); + } + } + else { + if (RETVAL_len_) { + PUSHs(sv_2mortal(newSVpv((char*)RETVAL, + (STRLEN)RETVAL_len_ * sizeof(jshort)))); + } + else + PUSHs(&sv_no); + } + (*env)->ReleaseShortArrayElements(env, array,RETVAL,JNI_ABORT); + RESTOREENV; + } + +jint * +GetIntArrayElements(array) + JNIEnv * env = FETCHENV; + jsize RETVAL_len_ = NO_INIT; + jintArray array + jboolean isCopy = NO_INIT; + PPCODE: + { + RETVAL = (*env)->GetIntArrayElements(env, array,&isCopy); + RETVAL_len_ = (*env)->GetArrayLength(env, array); + if (GIMME == G_ARRAY) { + int i; + jint* r = RETVAL; + EXTEND(sp, RETVAL_len_); + for (i = RETVAL_len_; i; --i) { + PUSHs(sv_2mortal(newSViv(*r++))); + } + } + else { + if (RETVAL_len_) { + PUSHs(sv_2mortal(newSVpv((char*)RETVAL, + (STRLEN)RETVAL_len_ * sizeof(jint)))); + } + else + PUSHs(&sv_no); + } + (*env)->ReleaseIntArrayElements(env, array,RETVAL,JNI_ABORT); + RESTOREENV; + } + +jlong * +GetLongArrayElements(array) + JNIEnv * env = FETCHENV; + jsize RETVAL_len_ = NO_INIT; + jlongArray array + jboolean isCopy = NO_INIT; + PPCODE: + { + RETVAL = (*env)->GetLongArrayElements(env, array,&isCopy); + RETVAL_len_ = (*env)->GetArrayLength(env, array); + if (GIMME == G_ARRAY) { + int i; + jlong* r = RETVAL; + EXTEND(sp, RETVAL_len_); + for (i = RETVAL_len_; i; --i) { + PUSHs(sv_2mortal(newSViv(*r++))); + } + } + else { + if (RETVAL_len_) { + PUSHs(sv_2mortal(newSVpv((char*)RETVAL, + (STRLEN)RETVAL_len_ * sizeof(jlong)))); + } + else + PUSHs(&sv_no); + } + (*env)->ReleaseLongArrayElements(env, array,RETVAL,JNI_ABORT); + RESTOREENV; + } + +jfloat * +GetFloatArrayElements(array) + JNIEnv * env = FETCHENV; + jsize RETVAL_len_ = NO_INIT; + jfloatArray array + jboolean isCopy = NO_INIT; + PPCODE: + { + RETVAL = (*env)->GetFloatArrayElements(env, array,&isCopy); + RETVAL_len_ = (*env)->GetArrayLength(env, array); + if (GIMME == G_ARRAY) { + int i; + jfloat* r = RETVAL; + EXTEND(sp, RETVAL_len_); + for (i = RETVAL_len_; i; --i) { + PUSHs(sv_2mortal(newSVnv(*r++))); + } + } + else { + if (RETVAL_len_) { + PUSHs(sv_2mortal(newSVpv((char*)RETVAL, + (STRLEN)RETVAL_len_ * sizeof(jfloat)))); + } + else + PUSHs(&sv_no); + } + (*env)->ReleaseFloatArrayElements(env, array,RETVAL,JNI_ABORT); + RESTOREENV; + } + +jdouble * +GetDoubleArrayElements(array) + JNIEnv * env = FETCHENV; + jsize RETVAL_len_ = NO_INIT; + jdoubleArray array + jboolean isCopy = NO_INIT; + PPCODE: + { + RETVAL = (*env)->GetDoubleArrayElements(env, array,&isCopy); + RETVAL_len_ = (*env)->GetArrayLength(env, array); + if (GIMME == G_ARRAY) { + int i; + jdouble* r = RETVAL; + EXTEND(sp, RETVAL_len_); + for (i = RETVAL_len_; i; --i) { + PUSHs(sv_2mortal(newSVnv(*r++))); + } + } + else { + if (RETVAL_len_) { + PUSHs(sv_2mortal(newSVpv((char*)RETVAL, + (STRLEN)RETVAL_len_ * sizeof(jdouble)))); + } + else + PUSHs(&sv_no); + } + (*env)->ReleaseDoubleArrayElements(env, array,RETVAL,JNI_ABORT); + RESTOREENV; + } + +void +GetBooleanArrayRegion(array,start,len,buf) + JNIEnv * env = FETCHENV; + jbooleanArray array + jsize start + jsize len + STRLEN tmplen = len * sizeof(jboolean) + 1; + char * tmpbuf = (char*)sv_pvn_force(ST(3), &tmplen); + jboolean * buf = (jboolean*)sv_grow(ST(3),len * sizeof(jboolean)+1); + CODE: + { + (*env)->GetBooleanArrayRegion(env, array,start,len,buf); + SvCUR_set(ST(3), len * sizeof(jboolean)); + *SvEND(ST(3)) = '\0'; + RESTOREENV; + } + +void +GetByteArrayRegion(array,start,len,buf) + JNIEnv * env = FETCHENV; + jbyteArray array + jsize start + jsize len + STRLEN tmplen = len * sizeof(jboolean) + 1; + char * tmpbuf = (char*)sv_pvn_force(ST(3), &tmplen); + jbyte * buf = (jbyte*)sv_grow(ST(3),len * sizeof(jbyte)+1); + CODE: + { + (*env)->GetByteArrayRegion(env, array,start,len,buf); + SvCUR_set(ST(3), len * sizeof(jbyte)); + *SvEND(ST(3)) = '\0'; + RESTOREENV; + } + +void +GetCharArrayRegion(array,start,len,buf) + JNIEnv * env = FETCHENV; + jcharArray array + jsize start + jsize len + STRLEN tmplen = len * sizeof(jboolean) + 1; + char * tmpbuf = (char*)sv_pvn_force(ST(3), &tmplen); + jchar * buf = (jchar*)sv_grow(ST(3),len * sizeof(jchar)+1); + CODE: + { + (*env)->GetCharArrayRegion(env, array,start,len,buf); + SvCUR_set(ST(3), len * sizeof(jchar)); + *SvEND(ST(3)) = '\0'; + RESTOREENV; + } + +void +GetShortArrayRegion(array,start,len,buf) + JNIEnv * env = FETCHENV; + jshortArray array + jsize start + jsize len + STRLEN tmplen = len * sizeof(jboolean) + 1; + char * tmpbuf = (char*)sv_pvn_force(ST(3), &tmplen); + jshort * buf = (jshort*)sv_grow(ST(3),len * sizeof(jshort)+1); + CODE: + { + (*env)->GetShortArrayRegion(env, array,start,len,buf); + SvCUR_set(ST(3), len * sizeof(jshort)); + *SvEND(ST(3)) = '\0'; + RESTOREENV; + } + +void +GetIntArrayRegion(array,start,len,buf) + JNIEnv * env = FETCHENV; + jintArray array + jsize start + jsize len + STRLEN tmplen = len * sizeof(jboolean) + 1; + char * tmpbuf = (char*)sv_pvn_force(ST(3), &tmplen); + jint * buf = (jint*)sv_grow(ST(3),len * sizeof(jint)+1); + CODE: + { + (*env)->GetIntArrayRegion(env, array,start,len,buf); + SvCUR_set(ST(3), len * sizeof(jint)); + *SvEND(ST(3)) = '\0'; + RESTOREENV; + } + +void +GetLongArrayRegion(array,start,len,buf) + JNIEnv * env = FETCHENV; + jlongArray array + jsize start + jsize len + STRLEN tmplen = len * sizeof(jboolean) + 1; + char * tmpbuf = (char*)sv_pvn_force(ST(3), &tmplen); + jlong * buf = (jlong*)sv_grow(ST(3),len * sizeof(jlong)+1); + CODE: + { + (*env)->GetLongArrayRegion(env, array,start,len,buf); + SvCUR_set(ST(3), len * sizeof(jlong)); + *SvEND(ST(3)) = '\0'; + RESTOREENV; + } + +void +GetFloatArrayRegion(array,start,len,buf) + JNIEnv * env = FETCHENV; + jfloatArray array + jsize start + jsize len + STRLEN tmplen = len * sizeof(jboolean) + 1; + char * tmpbuf = (char*)sv_pvn_force(ST(3), &tmplen); + jfloat * buf = (jfloat*)sv_grow(ST(3),len * sizeof(jfloat)+1); + CODE: + { + (*env)->GetFloatArrayRegion(env, array,start,len,buf); + SvCUR_set(ST(3), len * sizeof(jfloat)); + *SvEND(ST(3)) = '\0'; + RESTOREENV; + } + +void +GetDoubleArrayRegion(array,start,len,buf) + JNIEnv * env = FETCHENV; + jdoubleArray array + jsize start + jsize len + STRLEN tmplen = len * sizeof(jboolean) + 1; + char * tmpbuf = (char*)sv_pvn_force(ST(3), &tmplen); + jdouble * buf = (jdouble*)sv_grow(ST(3),len * sizeof(jdouble)+1); + CODE: + { + (*env)->GetDoubleArrayRegion(env, array,start,len,buf); + SvCUR_set(ST(3), len * sizeof(jdouble)); + *SvEND(ST(3)) = '\0'; + RESTOREENV; + } + +void +SetBooleanArrayRegion(array,start,len,buf) + JNIEnv * env = FETCHENV; + STRLEN tmplen = NO_INIT; + jbooleanArray array + jsize start + jsize len + jsize buf_len_ = NO_INIT; + jboolean * buf + CODE: + { + if (buf_len_ < len) + croak("string is too short"); + else if (buf_len_ > len && dowarn) + warn("string is too long"); + (*env)->SetBooleanArrayRegion(env, array,start,len,buf); + RESTOREENV; + } + +void +SetByteArrayRegion(array,start,len,buf) + JNIEnv * env = FETCHENV; + STRLEN tmplen = NO_INIT; + jbyteArray array + jsize start + jsize len + jsize buf_len_ = NO_INIT; + jbyte * buf + CODE: + { + if (buf_len_ < len) + croak("string is too short"); + else if (buf_len_ > len && dowarn) + warn("string is too long"); + (*env)->SetByteArrayRegion(env, array,start,len,buf); + RESTOREENV; + } + +void +SetCharArrayRegion(array,start,len,buf) + JNIEnv * env = FETCHENV; + STRLEN tmplen = NO_INIT; + jcharArray array + jsize start + jsize len + jsize buf_len_ = NO_INIT; + jchar * buf + CODE: + { + if (buf_len_ < len) + croak("string is too short"); + else if (buf_len_ > len && dowarn) + warn("string is too long"); + (*env)->SetCharArrayRegion(env, array,start,len,buf); + RESTOREENV; + } + +void +SetShortArrayRegion(array,start,len,buf) + JNIEnv * env = FETCHENV; + STRLEN tmplen = NO_INIT; + jshortArray array + jsize start + jsize len + jsize buf_len_ = NO_INIT; + jshort * buf + CODE: + { + if (buf_len_ < len) + croak("string is too short"); + else if (buf_len_ > len && dowarn) + warn("string is too long"); + (*env)->SetShortArrayRegion(env, array,start,len,buf); + RESTOREENV; + } + +void +SetIntArrayRegion(array,start,len,buf) + JNIEnv * env = FETCHENV; + STRLEN tmplen = NO_INIT; + jintArray array + jsize start + jsize len + jsize buf_len_ = NO_INIT; + jint * buf + CODE: + { + if (buf_len_ < len) + croak("string is too short"); + else if (buf_len_ > len && dowarn) + warn("string is too long"); + (*env)->SetIntArrayRegion(env, array,start,len,buf); + RESTOREENV; + } + +void +SetLongArrayRegion(array,start,len,buf) + JNIEnv * env = FETCHENV; + STRLEN tmplen = NO_INIT; + jlongArray array + jsize start + jsize len + jsize buf_len_ = NO_INIT; + jlong * buf + CODE: + { + if (buf_len_ < len) + croak("string is too short"); + else if (buf_len_ > len && dowarn) + warn("string is too long"); + (*env)->SetLongArrayRegion(env, array,start,len,buf); + RESTOREENV; + } + +void +SetFloatArrayRegion(array,start,len,buf) + JNIEnv * env = FETCHENV; + STRLEN tmplen = NO_INIT; + jfloatArray array + jsize start + jsize len + jsize buf_len_ = NO_INIT; + jfloat * buf + CODE: + { + if (buf_len_ < len) + croak("string is too short"); + else if (buf_len_ > len && dowarn) + warn("string is too long"); + (*env)->SetFloatArrayRegion(env, array,start,len,buf); + RESTOREENV; + } + +void +SetDoubleArrayRegion(array,start,len,buf) + JNIEnv * env = FETCHENV; + STRLEN tmplen = NO_INIT; + jdoubleArray array + jsize start + jsize len + jsize buf_len_ = NO_INIT; + jdouble * buf + CODE: + { + if (buf_len_ < len) + croak("string is too short"); + else if (buf_len_ > len && dowarn) + warn("string is too long"); + (*env)->SetDoubleArrayRegion(env, array,start,len,buf); + RESTOREENV; + } + +SysRet +RegisterNatives(clazz,methods,nMethods) + JNIEnv * env = FETCHENV; + jclass clazz + JNINativeMethod * methods + jint nMethods + CODE: + { + RETVAL = (*env)->RegisterNatives(env, clazz,methods,nMethods); + } + +SysRet +UnregisterNatives(clazz) + JNIEnv * env = FETCHENV; + jclass clazz + CODE: + { + RETVAL = (*env)->UnregisterNatives(env, clazz); + } + OUTPUT: + RETVAL + +SysRet +MonitorEnter(obj) + JNIEnv * env = FETCHENV; + jobject obj + CODE: + { + RETVAL = (*env)->MonitorEnter(env, obj); + RESTOREENV; + } + OUTPUT: + RETVAL + +SysRet +MonitorExit(obj) + JNIEnv * env = FETCHENV; + jobject obj + CODE: + { + RETVAL = (*env)->MonitorExit(env, obj); + RESTOREENV; + } + OUTPUT: + RETVAL + +JavaVM * +GetJavaVM(...) + JNIEnv * env = FETCHENV; + CODE: + { + if (env) { /* We're embedded. */ + if ((*env)->GetJavaVM(env, &RETVAL) < 0) + RETVAL = 0; + } + else { /* We're embedding. */ + JDK1_1InitArgs vm_args; + char *lib; + + if (items--) { + ++mark; + lib = SvPV(*mark, na); + } + else + lib = 0; + + if (!dlopen("libjava.so", RTLD_LAZY|RTLD_GLOBAL)) { + if (lib && !dlopen(lib, RTLD_LAZY|RTLD_GLOBAL)) + croak("Can't load libjava.so"); + } + + JNI_GetDefaultJavaVMInitArgs(&vm_args); + vm_args.exit = &call_my_exit; + while (items > 1) { + char *s = SvPV(*++mark,na); + items -= 2; + if (strEQ(s, "checkSource")) + vm_args.checkSource = (jint)SvIV(*++mark); + else if (strEQ(s, "nativeStackSize")) + vm_args.nativeStackSize = (jint)SvIV(*++mark); + else if (strEQ(s, "javaStackSize")) + vm_args.javaStackSize = (jint)SvIV(*++mark); + else if (strEQ(s, "minHeapSize")) + vm_args.minHeapSize = (jint)SvIV(*++mark); + else if (strEQ(s, "maxHeapSize")) + vm_args.maxHeapSize = (jint)SvIV(*++mark); + else if (strEQ(s, "verifyMode")) + vm_args.verifyMode = (jint)SvIV(*++mark); + else if (strEQ(s, "classpath")) + vm_args.classpath = savepv(SvPV(*++mark,na)); + else if (strEQ(s, "enableClassGC")) + vm_args.enableClassGC = (jint)SvIV(*++mark); + else if (strEQ(s, "enableVerboseGC")) + vm_args.enableVerboseGC = (jint)SvIV(*++mark); + else if (strEQ(s, "disableAsyncGC")) + vm_args.disableAsyncGC = (jint)SvIV(*++mark); + else if (strEQ(s, "verbose")) + vm_args.verbose = (jint)SvIV(*++mark); + else if (strEQ(s, "debugging")) + vm_args.debugging = (jboolean)SvIV(*++mark); + else if (strEQ(s, "debugPort")) + vm_args.debugPort = (jint)SvIV(*++mark); + else + croak("unrecognized option: %s", s); + } + JNI_CreateJavaVM(&RETVAL, &jplcurenv, &vm_args); + } + } + diff --git a/JNI/MANIFEST b/JNI/MANIFEST new file mode 100644 index 0000000..14a0f6c --- /dev/null +++ b/JNI/MANIFEST @@ -0,0 +1,6 @@ +Changes +JNI.pm +JNI.xs +MANIFEST +Makefile.PL +test.pl diff --git a/JNI/Makefile.PL b/JNI/Makefile.PL new file mode 100644 index 0000000..2611ff1 --- /dev/null +++ b/JNI/Makefile.PL @@ -0,0 +1,24 @@ +#!/usr/bin/perl + +$JPL_SRC = ".."; + +use ExtUtils::MakeMaker; +use Config; + +eval `$JPL_SRC/setvars -perl`; + +$java = $ENV{JAVA_HOME}; +$jpl = $ENV{JPL_HOME}; + +$ARCHNAME = $Config{archname}; + +# See lib/ExtUtils/MakeMaker.pm for details of how to influence +# the contents of the Makefile that is written. +WriteMakefile( + NAME => 'JNI', + VERSION_FROM => 'JNI.pm', + LIBS => ["-R$Config{archlib}/CORE -L$Config{archlib}/CORE -R$jpl/lib/$ARCHNAME -L$jpl/lib/$ARCHNAME -lperl -lPerlInterpreter"], + DEFINE => '', + LINKTYPE => 'dynamic', + INC => "-I$java/include -I$java/include/$^O -I$java/include/genunix", +); diff --git a/JNI/test.pl b/JNI/test.pl new file mode 100644 index 0000000..816e28b --- /dev/null +++ b/JNI/test.pl @@ -0,0 +1,20 @@ +# Before `make install' is performed this script should be runnable with +# `make test'. After `make install' it should work as `perl test.pl' + +######################### We start with some black magic to print on failure. + +# Change 1..1 below to 1..last_test_to_print . +# (It may become useful if the test is moved to ./t subdirectory.) + +BEGIN { $| = 1; print "1..1\n"; } +END {print "not ok 1\n" unless $loaded;} +use JNI; +$loaded = 1; +print "ok 1\n"; + +######################### End of black magic. + +# Insert your test code below (better if it prints "ok 13" +# (correspondingly "not ok 13") depending on the success of chunk 13 +# of the test code): + diff --git a/JNI/typemap b/JNI/typemap new file mode 100644 index 0000000..c5b15f6 --- /dev/null +++ b/JNI/typemap @@ -0,0 +1,386 @@ +JavaVM * T_JPTROBJ +JNINativeMethod * T_JPTROBJ +const char * T_PV +const jbyte * T_JMEM +const jchar * T_JMEM +jarray T_JPTROBJ +jboolean T_IV +jboolean * T_JMEM +jbooleanArray T_JPTROBJ +jbyte T_IV +jbyte * T_JMEM +jbyteArray T_JPTROBJ +jchar T_IV +jchar * T_JMEM +jcharArray T_JPTROBJ +jclass T_JPTROBJ +jdouble T_NV +jdouble * T_JMEM +jdoubleArray T_JPTROBJ +jfieldID T_JIDSIG +jfloat T_NV +jfloat * T_JMEM +jfloatArray T_JPTROBJ +jint T_IV +jint * T_JMEM +jintArray T_JPTROBJ +jlong T_NV +jlong * T_JMEM +jlongArray T_JPTROBJ +jmethodID T_JIDSIG +jobject T_JPTROBJ +jobjectArray T_JPTROBJ +jshort T_IV +jshort * T_JMEM +jshortArray T_JPTROBJ +jsize T_IV +jstring T_JSTRING +jthrowable T_JPTROBJ +jvalue * T_JVALUELIST + +INPUT +T_JMEM + { + $var = ($type)SvPV($arg,tmplen); + ${var}_len_ = (jsize) tmplen / sizeof(${subtype}); + } +T_JSTRING + if (SvROK($arg)) { + $var = ($type)(void*)SvIV(SvRV($arg)); + } + else + $var = ($type)(*env)->NewStringUTF(env, (char *) SvPV($arg,na)) +T_JVALUELIST + if (SvROK($arg)) { + AV* av = (AV*)SvRV($arg); + if (SvTYPE(av) == SVt_PVAV) { + I32 maxarg = AvFILL(av) + 1; + $var = makeargs(sig, AvARRAY(av), maxarg); + } + else + croak(\"$var is not an array reference\"); + } + else + croak(\"$var is not a reference\") +T_JIDSIG + { + $var = ($type)SvIV($arg); + sig = (char*)SvPV($arg,na); + } +T_JPTROBJ + if (SvROK($arg) && SvOBJECT(SvRV($arg))) { + IV tmp = SvIV((SV*)SvRV($arg)); + $var = ($type) tmp; + } + else + croak(\"$var is not of type ${ntype}\") + +OUTPUT +T_JMEM + sv_setpvn((SV*)$arg, (char*)$var, (STRLEN)${var}_len_ * sizeof(${subtype})); +T_JSTRING + { + static HV* ${var}_stashhv_ = 0; + if (!${var}_stashhv_) + ${var}_stashhv_ = gv_stashpv("java::lang::String", TRUE); + + sv_bless( + sv_setref_iv($arg, Nullch, (IV)(void*)${var}), + ${var}_stashhv_); + + } +T_JIDSIG + sv_setiv($arg, (IV)(void*)$var); + sv_setpv($arg, (char*)sig); + SvIOK_on($arg); +T_JPTROBJ + sv_setref_pv($arg, \"${ntype}\", (void*)$var); + +# basic C types +# int T_IV +# unsigned T_IV +# unsigned int T_IV +# long T_IV +# unsigned long T_IV +# short T_IV +# unsigned short T_IV +# char T_CHAR +# unsigned char T_U_CHAR +# char * T_PV +# unsigned char * T_PV +# caddr_t T_PV +# wchar_t * T_PV +# wchar_t T_IV +# bool_t T_IV +# size_t T_IV +# ssize_t T_IV +# time_t T_NV +# unsigned long * T_OPAQUEPTR +# char ** T_PACKED +# void * T_PTR +# Time_t * T_PV +# SV * T_SV +# SVREF T_SVREF +# AV * T_AVREF +# HV * T_HVREF +# CV * T_CVREF +# +# IV T_IV +# I32 T_IV +# I16 T_IV +# I8 T_IV +# U32 T_U_LONG +# U16 T_U_SHORT +# U8 T_IV +# Result T_U_CHAR +# Boolean T_IV +# double T_DOUBLE +# SysRet T_SYSRET +# SysRetLong T_SYSRET +# FILE * T_IN +# FileHandle T_PTROBJ +# InputStream T_IN +# InOutStream T_INOUT +# OutputStream T_OUT +# bool T_BOOL +# +############################################################################# +# INPUT +# T_SV +# $var = $arg +# T_SVREF +# if (sv_isa($arg, \"${ntype}\")) +# $var = (SV*)SvRV($arg); +# else +# croak(\"$var is not of type ${ntype}\") +# T_AVREF +# if (sv_isa($arg, \"${ntype}\")) +# $var = (AV*)SvRV($arg); +# else +# croak(\"$var is not of type ${ntype}\") +# T_HVREF +# if (sv_isa($arg, \"${ntype}\")) +# $var = (HV*)SvRV($arg); +# else +# croak(\"$var is not of type ${ntype}\") +# T_CVREF +# if (sv_isa($arg, \"${ntype}\")) +# $var = (CV*)SvRV($arg); +# else +# croak(\"$var is not of type ${ntype}\") +# T_SYSRET +# $var NOT IMPLEMENTED +# T_IV +# $var = ($type)SvIV($arg) +# T_INT +# $var = (int)SvIV($arg) +# T_ENUM +# $var = ($type)SvIV($arg) +# T_BOOL +# $var = (int)SvIV($arg) +# T_U_INT +# $var = (unsigned int)SvIV($arg) +# T_SHORT +# $var = (short)SvIV($arg) +# T_U_SHORT +# $var = (unsigned short)SvIV($arg) +# T_LONG +# $var = (long)SvIV($arg) +# T_U_LONG +# $var = (unsigned long)SvIV($arg) +# T_CHAR +# $var = (char)*SvPV($arg,na) +# T_U_CHAR +# $var = (unsigned char)SvIV($arg) +# T_FLOAT +# $var = (float)SvNV($arg) +# T_NV +# $var = ($type)SvNV($arg) +# T_DOUBLE +# $var = (double)SvNV($arg) +# T_PV +# $var = ($type)SvPV($arg,na) +# T_PTR +# $var = ($type)SvIV($arg) +# T_PTRREF +# if (SvROK($arg)) { +# IV tmp = SvIV((SV*)SvRV($arg)); +# $var = ($type) tmp; +# } +# else +# croak(\"$var is not a reference\") +# T_REF_IV_REF +# if (sv_isa($arg, \"${type}\")) { +# IV tmp = SvIV((SV*)SvRV($arg)); +# $var = *($type *) tmp; +# } +# else +# croak(\"$var is not of type ${ntype}\") +# T_REF_IV_PTR +# if (sv_isa($arg, \"${type}\")) { +# IV tmp = SvIV((SV*)SvRV($arg)); +# $var = ($type) tmp; +# } +# else +# croak(\"$var is not of type ${ntype}\") +# T_PTROBJ +# if (sv_derived_from($arg, \"${ntype}\")) { +# IV tmp = SvIV((SV*)SvRV($arg)); +# $var = ($type) tmp; +# } +# else +# croak(\"$var is not of type ${ntype}\") +# T_PTRDESC +# if (sv_isa($arg, \"${ntype}\")) { +# IV tmp = SvIV((SV*)SvRV($arg)); +# ${type}_desc = (\U${type}_DESC\E*) tmp; +# $var = ${type}_desc->ptr; +# } +# else +# croak(\"$var is not of type ${ntype}\") +# T_REFREF +# if (SvROK($arg)) { +# IV tmp = SvIV((SV*)SvRV($arg)); +# $var = *($type) tmp; +# } +# else +# croak(\"$var is not a reference\") +# T_REFOBJ +# if (sv_isa($arg, \"${ntype}\")) { +# IV tmp = SvIV((SV*)SvRV($arg)); +# $var = *($type) tmp; +# } +# else +# croak(\"$var is not of type ${ntype}\") +# T_OPAQUE +# $var NOT IMPLEMENTED +# T_OPAQUEPTR +# $var = ($type)SvPV($arg,na) +# T_PACKED +# $var = XS_unpack_$ntype($arg) +# T_PACKEDARRAY +# $var = XS_unpack_$ntype($arg) +# T_CALLBACK +# $var = make_perl_cb_$type($arg) +# T_ARRAY +# $var = $ntype(items -= $argoff); +# U32 ix_$var = $argoff; +# while (items--) { +# DO_ARRAY_ELEM; +# } +# T_IN +# $var = IoIFP(sv_2io($arg)) +# T_INOUT +# $var = IoIFP(sv_2io($arg)) +# T_OUT +# $var = IoOFP(sv_2io($arg)) +############################################################################## +# OUTPUT +# T_SV +# $arg = $var; +# T_SVREF +# $arg = newRV((SV*)$var); +# T_AVREF +# $arg = newRV((SV*)$var); +# T_HVREF +# $arg = newRV((SV*)$var); +# T_CVREF +# $arg = newRV((SV*)$var); +# T_IV +# sv_setiv($arg, (IV)$var); +# T_INT +# sv_setiv($arg, (IV)$var); +# T_SYSRET +# if ($var != -1) { +# if ($var == 0) +# sv_setpvn($arg, "0 but true", 10); +# else +# sv_setiv($arg, (IV)$var); +# } +# T_ENUM +# sv_setiv($arg, (IV)$var); +# T_BOOL +# $arg = boolSV($var); +# T_U_INT +# sv_setiv($arg, (IV)$var); +# T_SHORT +# sv_setiv($arg, (IV)$var); +# T_U_SHORT +# sv_setiv($arg, (IV)$var); +# T_LONG +# sv_setiv($arg, (IV)$var); +# T_U_LONG +# sv_setiv($arg, (IV)$var); +# T_CHAR +# sv_setpvn($arg, (char *)&$var, 1); +# T_U_CHAR +# sv_setiv($arg, (IV)$var); +# T_FLOAT +# sv_setnv($arg, (double)$var); +# T_NV +# sv_setnv($arg, (double)$var); +# T_DOUBLE +# sv_setnv($arg, (double)$var); +# T_PV +# sv_setpv((SV*)$arg, $var); +# T_PTR +# sv_setiv($arg, (IV)$var); +# T_PTRREF +# sv_setref_pv($arg, Nullch, (void*)$var); +# T_REF_IV_REF +# sv_setref_pv($arg, \"${ntype}\", (void*)new $ntype($var)); +# T_REF_IV_PTR +# sv_setref_pv($arg, \"${ntype}\", (void*)$var); +# T_PTROBJ +# sv_setref_pv($arg, \"${ntype}\", (void*)$var); +# T_PTRDESC +# sv_setref_pv($arg, \"${ntype}\", (void*)new\U${type}_DESC\E($var)); +# T_REFREF +# sv_setrefref($arg, \"${ntype}\", XS_service_$ntype, +# ($var ? (void*)new $ntype($var) : 0)); +# T_REFOBJ +# NOT IMPLEMENTED +# T_OPAQUE +# sv_setpvn($arg, (char *)&$var, sizeof($var)); +# T_OPAQUEPTR +# sv_setpvn($arg, (char *)$var, sizeof(*$var)), XFree((char *)$var); +# T_PACKED +# XS_pack_$ntype($arg, $var); +# T_PACKEDARRAY +# XS_pack_$ntype($arg, $var, count_$ntype); +# T_DATAUNIT +# sv_setpvn($arg, $var.chp(), $var.size()); +# T_CALLBACK +# sv_setpvn($arg, $var.context.value().chp(), +# $var.context.value().size()); +# T_ARRAY +# ST_EXTEND($var.size); +# for (U32 ix_$var = 0; ix_$var < $var.size; ix_$var++) { +# ST(ix_$var) = sv_newmortal(); +# DO_ARRAY_ELEM +# } +# sp += $var.size - 1; +# T_IN +# { +# GV *gv = newGVgen("$Package"); +# if ( do_open(gv, "<&", 2, FALSE, 0, 0, $var) ) +# sv_setsv($arg, sv_bless(newRV((SV*)gv), gv_stashpv("$Package",1))); +# else +# $arg = &sv_undef; +# } +# T_INOUT +# { +# GV *gv = newGVgen("$Package"); +# if ( do_open(gv, "+<&", 3, FALSE, 0, 0, $var) ) +# sv_setsv($arg, sv_bless(newRV((SV*)gv), gv_stashpv("$Package",1))); +# else +# $arg = &sv_undef; +# } +# T_OUT +# { +# GV *gv = newGVgen("$Package"); +# if ( do_open(gv, "+>&", 3, FALSE, 0, 0, $var) ) +# sv_setsv($arg, sv_bless(newRV((SV*)gv), gv_stashpv("$Package",1))); +# else +# $arg = &sv_undef; +# } diff --git a/JPL/AutoLoader.pm b/JPL/AutoLoader.pm new file mode 100644 index 0000000..94d9856 --- /dev/null +++ b/JPL/AutoLoader.pm @@ -0,0 +1,352 @@ +package JPL::AutoLoader; + +use strict; + +use vars qw(@ISA @EXPORT $AUTOLOAD); + +use Exporter; +@ISA = "Exporter"; +@EXPORT = ("AUTOLOAD", "getmeth"); + +my %callmethod = ( + V => 'Void', + Z => 'Boolean', + B => 'Byte', + C => 'Char', + S => 'Short', + I => 'Int', + J => 'Long', + F => 'Float', + D => 'Double', +); + +# A lookup table to convert the data types that Java +# developers are used to seeing into the JNI-mangled +# versions. +# +# bjepson 13 August 1997 +# +my %type_table = ( + 'void' => 'V', + 'boolean' => 'Z', + 'byte' => 'B', + 'char' => 'C', + 'short' => 'S', + 'int' => 'I', + 'long' => 'J', + 'float' => 'F', + 'double' => 'D' +); + +# A cache for method ids. +# +# bjepson 13 August 1997 +# +my %MID_CACHE; + +# A cache for methods. +# +# bjepson 13 August 1997 +# +my %METHOD_CACHE; + +use JNI; + +# XXX We're assuming for the moment that method ids are persistent... + +sub AUTOLOAD { + + print "AUTOLOAD $AUTOLOAD(@_)\n" if $JPL::DEBUG; + my ($classname, $methodsig) = $AUTOLOAD =~ /^(.*)::(.*)/; + print "class = $classname, method = $methodsig\n" if $JPL::DEBUG; + + if ($methodsig eq "DESTROY") { + print "sub $AUTOLOAD {}\n" if $JPL::DEBUG; + eval "sub $AUTOLOAD {}"; + return; + } + + (my $jclassname = $classname) =~ s/^JPL:://; + $jclassname =~ s{::}{/}g; + my $class = JNI::FindClass($jclassname) + or die "Can't find Java class $jclassname\n"; + + # This method lookup allows the user to pass in + # references to two array that contain the input and + # output data types of the method. + # + # bjepson 13 August 1997 + # + my ($methodname, $sig, $retsig, $slow_way); + if (ref $_[1] eq 'ARRAY' && ref $_[2] eq 'ARRAY') { + + $slow_way = 1; + + # First we strip out the input and output args. + # + my ($in,$out) = splice(@_, 1, 2); + + # let's mangle up the input argument types. + # + my @in = jni_mangle($in); + + # if they didn't hand us any output values types, make + # them void by default. + # + unless (@{ $out }) { + $out = ['void']; + } + + # mangle the output types + # + my @out = jni_mangle($out); + + $methodname = $methodsig; + $retsig = join("", @out); + $sig = "(" . join("", @in) . ")" . $retsig; + + } else { + + ($methodname, $sig) = split /__/, $methodsig, 2; + $sig ||= "__V"; # default is void return + + # Now demangle the signature. + + $sig =~ s/_3/[/g; + $sig =~ s/_2/;/g; + my $tmp; + $sig =~ s{ + (s|L[^;]*;) + }{ + $1 eq 's' + ? "Ljava/lang/String;" + : (($tmp = $1) =~ tr[_][/], $tmp) + }egx; + if ($sig =~ s/(.*)__(.*)/($1)$2/) { + $retsig = $2; + } + else { # void return is assumed + $sig = "($sig)V"; + $retsig = "V"; + } + $sig =~ s/_1/_/g; + } + print "sig = $sig\n" if $JPL::DEBUG; + + # Now look up the method's ID somehow or other. + # + $methodname = "" if $methodname eq 'new'; + my $mid; + + # Added a method id cache to compensate for avoiding + # Perl's method cache... + # + if ($MID_CACHE{qq[$classname:$methodname:$sig]}) { + + $mid = $MID_CACHE{qq[$classname:$methodname:$sig]}; + print "got method " . ($mid + 0) . " from cache.\n" if $JPL::DEBUG; + + } elsif (ref $_[0] or $methodname eq '') { + + # Look up an instance method or a constructor + # + $mid = JNI::GetMethodID($class, $methodname, $sig); + + } else { + + # Look up a static method + # + $mid = JNI::GetStaticMethodID($class, $methodname, $sig); + + } + + # Add this method to the cache. + # + # bjepson 13 August 1997 + # + $MID_CACHE{qq[$classname:$methodname:$sig]} = $mid if $slow_way; + + if ($mid == 0) { + + JNI::ExceptionClear(); + # Could do some guessing here on return type... + die "Can't get method id for $AUTOLOAD($sig)\n"; + + } + + print "mid = ", $mid + 0, ", $mid\n" if $JPL::DEBUG; + my $rettype = $callmethod{$retsig} || "Object"; + print "*** rettype = $rettype\n" if $JPL::DEBUG; + + my $blesspack; + no strict 'refs'; + if ($rettype eq "Object") { + $blesspack = $retsig; + $blesspack =~ s/^L//; + $blesspack =~ s/;$//; + $blesspack =~ s#/#::#g; + print "*** Some sort of wizardry...\n" if $JPL::DEBUG; + print %{$blesspack . "::"}, "\n" if $JPL::DEBUG; + print defined %{$blesspack . "::"}, "\n" if $JPL::DEBUG; + if (not defined %{$blesspack . "::"}) { + #if ($blesspack eq "java::lang::String") { + if ($blesspack =~ /java::/) { + eval <<"END" . <<'ENDQ'; +package $blesspack; +END +use JPL::AutoLoader; +use overload + '""' => sub { JNI::GetStringUTFChars($_[0]) }, + '0+' => sub { 0 + "$_[0]" }, + fallback => 1; +ENDQ + } + else { + eval <<"END"; +package $blesspack; +use JPL::AutoLoader; +END + } + } + } + + # Finally, call the method. Er, somehow... + # + my $METHOD; + + my $real_mid = $mid + 0; # weird overloading that I + # don't understand ?! + if (ref ${$METHOD_CACHE{qq[$real_mid]}} eq 'CODE') { + + $METHOD = ${$METHOD_CACHE{qq[$real_mid]}}; + print qq[Pulled $classname, $methodname, $sig from cache.\n] if $JPL::DEBUG; + + } elsif ($methodname eq "") { + $METHOD = sub { + my $self = shift; + my $class = JNI::FindClass($jclassname); + bless $class->JNI::NewObjectA($mid, \@_), $classname; + }; + } + elsif (ref $_[0]) { + if ($blesspack) { + $METHOD = sub { + my $self = shift; + if (ref $self eq $classname) { + my $callmethod = "JNI::Call${rettype}MethodA"; + bless $self->$callmethod($mid, \@_), $blesspack; + } + else { + my $callmethod = "JNI::CallNonvirtual${rettype}MethodA"; + bless $self->$callmethod($class, $mid, \@_), $blesspack; + } + }; + } + else { + $METHOD = sub { + my $self = shift; + if (ref $self eq $classname) { + my $callmethod = "JNI::Call${rettype}MethodA"; + $self->$callmethod($mid, \@_); + } + else { + my $callmethod = "JNI::CallNonvirtual${rettype}MethodA"; + $self->$callmethod($class, $mid, \@_); + } + }; + } + } + else { + my $callmethod = "JNI::CallStatic${rettype}MethodA"; + if ($blesspack) { + $METHOD = sub { + my $self = shift; + bless $class->$callmethod($mid, \@_), $blesspack; + }; + } + else { + $METHOD = sub { + my $self = shift; + $class->$callmethod($mid, \@_); + }; + } + } + if ($slow_way) { + $METHOD_CACHE{qq[$real_mid]} = \$METHOD; + &$METHOD; + } + else { + *$AUTOLOAD = $METHOD; + goto &$AUTOLOAD; + } +} + +sub jni_mangle { + + my $arr = shift; + my @ret; + + foreach my $arg (@{ $arr }) { + + my $ret; + + # Count the dangling []s. + # + $ret = '[' x $arg =~ s/\[\]//g; + + # Is it a primitive type? + # + if ($type_table{$arg}) { + $ret .= $type_table{$arg}; + } else { + # some sort of class + # + $arg =~ s#\.#/#g; + $ret .= "L$arg;"; + } + push @ret, $ret; + + } + + return @ret; + +} + +sub getmeth { + my ($meth, $in, $out) = @_; + my @in = jni_mangle($in); + + # if they didn't hand us any output values types, make + # them void by default. + # + unless ($out and @$out) { + $out = ['void']; + } + + # mangle the output types + # + my @out = jni_mangle($out); + + my $sig = join("", '#', @in, '#', @out); + $sig =~ s/_/_1/g; + my $tmp; + $sig =~ s{ + (L[^;]*;) + }{ + ($tmp = $1) =~ tr[/][_], $tmp + }egx; + $sig =~ s{Ljava/lang/String;}{s}g; + $sig =~ s/;/_2/g; + $sig =~ s/\[/_3/g; + $sig =~ s/#/__/g; + $meth . $sig; +} + +{ + package java::lang::String; + use overload + '""' => sub { JNI::GetStringUTFChars($_[0]) }, + '0+' => sub { 0 + "$_[0]" }, + fallback => 1; +} +1; diff --git a/JPL/Class.pm b/JPL/Class.pm new file mode 100644 index 0000000..1bc9768 --- /dev/null +++ b/JPL/Class.pm @@ -0,0 +1,13 @@ +package JPL::Class; +use JPL::AutoLoader (); + +sub DESTROY {} + +sub import { + my $class = shift; + foreach $class (@_) { + *{$class . "::AUTOLOAD"} = *JPL::AutoLoader::AUTOLOAD; + *{$class . "::DESTROY"} = \&DESTROY; + } +} +1; diff --git a/JPL/Compile.pm b/JPL/Compile.pm new file mode 100755 index 0000000..39dd6b8 --- /dev/null +++ b/JPL/Compile.pm @@ -0,0 +1,772 @@ +#!/usr/bin/perl -w + +# Copyright 1997, O'Reilly & Associate, Inc. +# +# This package may be copied under the same terms as Perl itself. + +package JPL::Compile; +use Exporter (); +@ISA = qw(Exporter); +@EXPORT = qw(files file); + +use strict; + + +warn "You don't have a recent JDK kit your PATH, so this may fail.\n" + unless $ENV{PATH} =~ /(java|jdk1.[1-9])/; + +sub emit; + +my $PERL = ""; +my $LASTCLASS = ""; +my $PERLLINE = 0; +my $PROTO; + +my @protos; + +my $plfile; +my $jpfile; +my $hfile; +my $h_file; +my $cfile; +my $jfile; +my $classfile; + +my $DEBUG = $ENV{JPLDEBUG}; + +my %ptype = qw( + Z boolean + B byte + C char + S short + I int + J long + F float + D double +); + +$ENV{CLASSPATH} =~ s/^/.:/ unless $ENV{CLASSPATH} =~ /^\.(?::|$)/; + +unless (caller) { + files(@ARGV); +} + +####################################################################### + +sub files { + foreach my $jpfile (@_) { + file($jpfile); + } + print "make\n"; + system "make"; +} + +sub file { + my $jpfile = shift; + my $JAVA = ""; + my $lastpos = 0; + my $linenum = 2; + my %classseen; + my %fieldsig; + my %staticfield; + + (my $file = $jpfile) =~ s/\.jpl$//; + $jpfile = "$file.jpl"; + $jfile = "$file.java"; + $hfile = "$file.h"; + $cfile = "$file.c"; + $plfile = "$file.pl"; + $classfile = "$file.class"; + + ($h_file = $hfile) =~ s/_/_0005f/g; + + emit_c_header(); + + # Extract out arg names from .java file, since .class doesn't have 'em. + + open(JPFILE, $jpfile) or die "Can't open $jpfile: $!\n"; + undef $/; + $_ = ; + close JPFILE; + + die "$jpfile doesn't seem to define class $file!\n" + unless /class\s+\b$file\b[\w\s.,]*{/; + + @protos = (); + open(JFILE, ">$jfile") or die "Can't create $jfile: $!\n"; + + while (m/\bperl\b([^\n]*?\b(\w+)\s*\(\s*(.*?)\s*\)[\s\w.,]*)\{\{(.*?)\}\}/sg) { + $JAVA = substr($`, $lastpos); + $lastpos = pos $_; + $JAVA .= "native"; + $JAVA .= $1; + + my $method = $2; + + my $proto = $3; + + my $perl = $4; + (my $repl = $4) =~ tr/\n//cd; + $JAVA .= ';'; + $linenum += $JAVA =~ tr/\n/\n/; + $JAVA .= $repl; + print JFILE $JAVA; + + $proto =~ s/\s+/ /g; + $perl =~ s/^[ \t]+\Z//m; + $perl =~ s/^[ \t]*\n//; + push(@protos, [$method, $proto, $perl, $linenum]); + + $linenum += $repl =~ tr/\n/\n/; + } + + print JFILE <<"END"; + static { + System.loadLibrary("$file"); + PerlInterpreter pi = new PerlInterpreter().fetch(); + // pi.eval("\$JPL::DEBUG = \$ENV{JPLDEBUG};"); + pi.eval("warn qq{loading $file\\n} if \$JPL::DEBUG"); + pi.eval("eval {require '$plfile'}; print \$@ if \$@;"); + } +END + + print JFILE substr($_, $lastpos); + + close JFILE; + + # Produce the corresponding .h file. Should really use make... + + if (not -s $hfile or -M $hfile > -M $jfile) { + if (not -s $classfile or -M $classfile > -M $jfile) { + unlink $classfile; + print "javac $jfile\n"; + system "javac $jfile" and die "Couldn't run javac: exit $?\n"; + if (not -s $classfile or -M $classfile > -M $jfile) { + die "Couldn't produce $classfile from $jfile!"; + } + } + unlink $hfile; + print "javah -jni $file\n"; + system "javah -jni $file" and die "Couldn't run javah: exit $?\n"; + if (not -s $hfile and -s $h_file) { + rename $h_file, $hfile; + } + if (not -s $hfile or -M $hfile > -M $jfile) { + die "Couldn't produce $hfile from $classfile!"; + } + } + + # Easiest place to get fields is from javap. + + print "javap -s $file\n"; + open(JP, "javap -s $file|"); + $/ = "\n"; + while () { + if (/^\s+([A-Za-z_].*) (\w+)[\[\d\]]*;/) { + my $jtype = $1; + my $name = $2; + $_ = ; + s!^\s*/\*\s*!!; + s!\s*\*/\s*!!; + print "Field $jtype $name $_\n" if $DEBUG; + $fieldsig{$name} = $_; + $staticfield{$name} = $jtype =~ /\bstatic\b/; + } + while (m/L([^;]*);/g) { + my $pclass = j2p_class($1); + $classseen{$pclass}++; + } + } + close JP; + + open(HFILE, $hfile) or die "Couldn't open $hfile: $!\n"; + undef $/; + $_ = ; + close HFILE; + + die "panic: native method mismatch" if @protos != s/^JNIEXPORT/JNIEXPORT/gm; + + $PROTO = 0; + while (m{ + \*\s*Class:\s*(\w+)\s* + \*\s*Method:\s*(\w+)\s* + \*\s*Signature:\s*(\S+)\s*\*/\s* + JNIEXPORT\s*(.*?)\s*JNICALL\s*(\w+)\s*\((.*?)\) + }gx) { + my $class = $1; + my $method = $2; + my $signature = $3; + my $rettype = $4; + my $cname = $5; + my $ctypes = $6; + $class =~ s/_0005f/_/g; + if ($method ne $protos[$PROTO][0]) { + die "Method name mismatch: $method vs $protos[$PROTO][0]\n"; + } + print "$class.$method($protos[$PROTO][1]) => + $signature + $rettype $cname($ctypes)\n" if $DEBUG; + + # Insert argument names into parameter list. + + my $env = "env"; + my $obj = "obj"; + my @jargs = split(/\s*,\s*/, $protos[$PROTO][1]); + foreach my $arg (@jargs) { + $arg =~ s/^.*\b(\w+).*$/${1}/; + } + my @tmpargs = @jargs; + unshift(@tmpargs, $env, $obj); + print "\t@tmpargs\n" if $DEBUG; + $ctypes .= ","; + $ctypes =~ s/,/' ' . shift(@tmpargs) . '_,'/eg; + $ctypes =~ s/,$//; + $ctypes =~ s/env_/env/; + $ctypes =~ s/obj_/obj/; + print "\t$ctypes\n" if $DEBUG; + + my $jlen = @jargs + 1; + + (my $mangclass = $class) =~ s/_/_1/g; + (my $mangmethod = $method) =~ s/_/_1/g; + my $plname = $cname; + $plname =~ s/^Java_${mangclass}_${mangmethod}/JPL::${class}::${method}/; + $plname =~ s/Ljava_lang_String_2/s/g; + + # Make glue code for each argument. + + (my $sig = $signature) =~ s/^\(//; + + my $decls = ""; + my $glue = ""; + + foreach my $jarg (@jargs) { + if ($sig =~ s/^[ZBCSI]//) { + $glue .= <<""; +! /* $jarg */ +! PUSHs(sv_2mortal(newSViv(${jarg}_))); +! + + } + elsif ($sig =~ s/^[JFD]//) { + $glue .= <<""; +! /* $jarg */ +! PUSHs(sv_2mortal(newSVnv(${jarg}_))); +! + + } + elsif ($sig =~ s#^Ljava/lang/String;##) { + $glue .= <<""; +! /* $jarg */ +! tmpjb = (jbyte*)(*env)->GetStringUTFChars(env,${jarg}_,0); +! PUSHs(sv_2mortal(newSVpv((char*)tmpjb,0))); +! (*env)->ReleaseStringUTFChars(env,${jarg}_,tmpjb); +! + + } + elsif ($sig =~ s/^L([^;]*);//) { + my $pclass = j2p_class($1); + $classseen{$pclass}++; + $glue .= <<""; +! /* $jarg */ +! if (!${jarg}_stashhv_) +! ${jarg}_stashhv_ = gv_stashpv("$pclass", TRUE); +! +! PUSHs(sv_bless( +! sv_setref_iv(sv_newmortal(), Nullch, (IV)(void*)${jarg}_), +! ${jarg}_stashhv_)); +! if (jpldebug) +! fprintf(stderr, "Done with $jarg\\n"); +! + + $decls .= <<""; +! static HV* ${jarg}_stashhv_ = 0; + + + } + elsif ($sig =~ s/^\[+([ZBCSIJFD]|L[^;]*;)//) { + my $pclass = "jarray"; + $classseen{$pclass}++; + $glue .= <<""; +! /* $jarg */ +! if (!${jarg}_stashhv_) +! ${jarg}_stashhv_ = gv_stashpv("$pclass", TRUE); +! +! PUSHs(sv_bless( +! sv_setref_iv(sv_newmortal(), Nullch, (IV)(void*)${jarg}_), +! ${jarg}_stashhv_)); +! if (jpldebug) +! fprintf(stderr, "Done with $jarg\\n"); +! + + $decls .= <<""; +! static HV* ${jarg}_stashhv_ = 0; + + } + else { + die "Short signature: $signature\n" if $sig eq ""; + die "Unrecognized letter '" . substr($sig, 0, 1) . "' in signature $signature\n"; + } + } + + $sig =~ s/^\)// or die "Argument mismatch in signature: $method$signature\n"; + + my $void = $signature =~ /\)V$/; + + $decls .= <<"" if $signature =~ m#java/lang/String#; +! jbyte* tmpjb; + + $decls .= <<"" unless $void; +! SV* retsv; +! $rettype retval; +! +! if (jpldebug) +! fprintf(stderr, "Got to $cname\\n"); +! ENTER; +! SAVETMPS; + + emit <<""; +!JNIEXPORT $rettype JNICALL +!$cname($ctypes) +!{ +! static SV* methodsv = 0; +! static HV* stashhv = 0; +! dSP; +$decls +! PUSHMARK(sp); +! EXTEND(sp,$jlen); +! +! sv_setiv(perl_get_sv("JPL::_env_", 1), (IV)(void*)env); +! jplcurenv = env; +! +! if (jpldebug) +! fprintf(stderr, "env = %lx\\n", (long)$env); +! +! if (!methodsv) +! methodsv = (SV*)perl_get_cv("$plname", TRUE); +! if (!stashhv) +! stashhv = gv_stashpv("JPL::$class", TRUE); +! +! if (jpldebug) +! fprintf(stderr, "blessing obj = %lx\\n", obj); +! PUSHs(sv_bless( +! sv_setref_iv(sv_newmortal(), Nullch, (IV)(void*)obj), +! stashhv)); +! +$glue + + # Finally, call the subroutine. + + my $mod; + $mod = "|G_DISCARD" if $void; + + if ($void) { + emit <<""; +! PUTBACK; +! perl_call_sv(methodsv, G_EVAL|G_KEEPERR|G_DISCARD); +! + + } + else { + emit <<""; +! PUTBACK; +! if (perl_call_sv(methodsv, G_EVAL|G_KEEPERR)) +! retsv = *stack_sp--; +! else +! retsv = &sv_undef; +! + + } + + emit <<""; +! if (SvTRUE(GvSV(errgv))) { +! jthrowable newExcCls; +! +! (*env)->ExceptionDescribe(env); +! (*env)->ExceptionClear(env); +! +! newExcCls = (*env)->FindClass(env, "java/lang/RuntimeException"); +! if (newExcCls) +! (*env)->ThrowNew(env, newExcCls, SvPV(GvSV(errgv),na)); +! } +! + + # Fix up the return value, if any. + + if ($sig =~ s/^V//) { + emit <<""; +! return; + + } + elsif ($sig =~ s/^[ZBCSI]//) { + emit <<""; +! retval = ($rettype)SvIV(retsv); +! FREETMPS; +! LEAVE; +! return retval; + + } + elsif ($sig =~ s/^[JFD]//) { + emit <<""; +! retval = ($rettype)SvNV(retsv); +! FREETMPS; +! LEAVE; +! return retval; + + } + elsif ($sig =~ s#^Ljava/lang/String;##) { + emit <<""; +! retval = (*env)->NewStringUTF(env, SvPV(retsv,na)); +! FREETMPS; +! LEAVE; +! return retval; + + } + elsif ($sig =~ s/^L[^;]*;//) { + emit <<""; +! if (SvROK(retsv)) { +! SV* rv = (SV*)SvRV(retsv); +! if (SvOBJECT(rv)) +! retval = ($rettype)(void*)SvIV(rv); +! else +! retval = ($rettype)(void*)0; +! } +! else +! retval = ($rettype)(void*)0; +! FREETMPS; +! LEAVE; +! return retval; + + } + elsif ($sig =~ s/^\[([ZBCSIJFD])//) { + my $elemtype = $1; + my $ptype = "\u$ptype{$elemtype}"; + my $ntype = "j$ptype{$elemtype}"; + my $in = $elemtype =~ /^[JFD]/ ? "N" : "I"; + emit <<""; +! if (SvROK(retsv)) { +! SV* rv = (SV*)SvRV(retsv); +! if (SvOBJECT(rv)) +! retval = ($rettype)(void*)SvIV(rv); +! else if (SvTYPE(rv) == SVt_PVAV) { +! jsize len = av_len((AV*)rv) + 1; +! $ntype* buf = ($ntype*)malloc(len * sizeof($ntype)); +! int i; +! SV** esv; +! +! ${ntype}Array ja = (*env)->New${ptype}Array(env, len); +! for (esv = AvARRAY((AV*)rv), i = 0; i < len; esv++, i++) +! buf[i] = ($ntype)Sv${in}V(*esv); +! (*env)->Set${ptype}ArrayRegion(env, ja, 0, len, buf); +! free((void*)buf); +! retval = ($rettype)ja; +! } +! else +! retval = ($rettype)(void*)0; +! } +! else if (SvPOK(retsv)) { +! jsize len = sv_len(retsv) / sizeof($ntype); +! +! ${ntype}Array ja = (*env)->New${ptype}Array(env, len); +! (*env)->Set${ptype}ArrayRegion(env, ja, 0, len, ($ntype*)SvPV(retsv,na)); +! retval = ($rettype)ja; +! } +! else +! retval = ($rettype)(void*)0; +! FREETMPS; +! LEAVE; +! return retval; + + } + elsif ($sig =~ s!^\[Ljava/lang/String;!!) { + emit <<""; +! if (SvROK(retsv)) { +! SV* rv = (SV*)SvRV(retsv); +! if (SvOBJECT(rv)) +! retval = ($rettype)(void*)SvIV(rv); +! else if (SvTYPE(rv) == SVt_PVAV) { +! jsize len = av_len((AV*)rv) + 1; +! int i; +! SV** esv; +! static jclass jcl = 0; +! jarray ja; +! +! if (!jcl) +! jcl = (*env)->FindClass(env, "java/lang/String"); +! ja = (*env)->NewObjectArray(env, len, jcl, 0); +! for (esv = AvARRAY((AV*)rv), i = 0; i < len; esv++, i++) { +! jobject str = (jobject)(*env)->NewStringUTF(env, SvPV(*esv,na)); +! (*env)->SetObjectArrayElement(env, ja, i, str); +! } +! retval = ($rettype)ja; +! } +! else +! retval = ($rettype)(void*)0; +! } +! else +! retval = ($rettype)(void*)0; +! FREETMPS; +! LEAVE; +! return retval; + + } + elsif ($sig =~ s/^(\[+)([ZBCSIJFD]|L[^;]*;)//) { + my $arity = length $1; + my $elemtype = $2; + emit <<""; +! if (SvROK(retsv)) { +! SV* rv = (SV*)SvRV(retsv); +! if (SvOBJECT(rv)) +! retval = ($rettype)(void*)SvIV(rv); +! else if (SvTYPE(rv) == SVt_PVAV) { +! jsize len = av_len((AV*)rv) + 1; +! int i; +! SV** esv; +! static jclass jcl = 0; +! jarray ja; +! +! if (!jcl) +! jcl = (*env)->FindClass(env, "java/lang/Object"); +! ja = (*env)->NewObjectArray(env, len, jcl, 0); +! for (esv = AvARRAY((AV*)rv), i = 0; i < len; esv++, i++) { +! if (SvROK(*esv) && (rv = SvRV(*esv)) && SvOBJECT(rv)) { +! (*env)->SetObjectArrayElement(env, ja, i, +! (jobject)(void*)SvIV(rv)); +! } +! else { +! jobject str = (jobject)(*env)->NewStringUTF(env, +! SvPV(*esv,na)); +! (*env)->SetObjectArrayElement(env, ja, i, str); +! } +! } +! retval = ($rettype)ja; +! } +! else +! retval = ($rettype)(void*)0; +! } +! else +! retval = ($rettype)(void*)0; +! FREETMPS; +! LEAVE; +! return retval; + + } + else { + die "No return type: $signature\n" if $sig eq ""; + die "Unrecognized return type '" . substr($sig, 0, 1) . "' in signature $signature\n"; + } + + emit <<""; +!} +! + + my $perl = ""; + + if ($class ne $LASTCLASS) { + $LASTCLASS = $class; + $perl .= <<""; +package JPL::${class}; +use JNI; +use JPL::AutoLoader; +\@ISA = qw(jobject); +\$clazz = JNI::FindClass("$file");\n + + foreach my $field (sort keys %fieldsig) { + my $sig = $fieldsig{$field}; + my $ptype = $ptype{$sig}; + if ($ptype) { + $ptype = "\u$ptype"; + if ($staticfield{$field}) { + $perl .= <<""; +\$${field}_FieldID = JNI::GetStaticFieldID(\$clazz, "$field", "$sig"); +sub $field (\$;\$) { + my \$self = shift; + if (\@_) { + JNI::SetStatic${ptype}Field(\$clazz, \$${field}_FieldID, \$_[0]); + } + else { + JNI::GetStatic${ptype}Field(\$clazz, \$${field}_FieldID); + } +}\n + + } + else { + $perl .= <<""; +\$${field}_FieldID = JNI::GetFieldID(\$clazz, "$field", "$sig"); +sub $field (\$;\$) { + my \$self = shift; + if (\@_) { + JNI::Set${ptype}Field(\$self, \$${field}_FieldID, \$_[0]); + } + else { + JNI::Get${ptype}Field(\$self, \$${field}_FieldID); + } +}\n + + } + } + else { + my $pltype = $sig; + if ($pltype =~ s/^L(.*);/$1/) { + $pltype =~ s!/!::!g; + } + else { + $pltype = 'jarray'; + } + if ($pltype eq "java::lang::String") { + if ($staticfield{$field}) { + $perl .= <<""; +\$${field}_FieldID = JNI::GetStaticFieldID(\$clazz, "$field", "$sig"); +sub $field (\$;\$) { + my \$self = shift; + if (\@_) { + JNI::SetStaticObjectField(\$clazz, \$${field}_FieldID, + ref \$_[0] ? \$_[0] : JNI::NewStringUTF(\$_[0])); + } + else { + JNI::GetStringUTFChars(JNI::GetStaticObjectField(\$clazz, \$${field}_FieldID)); + } +}\n + + } + else { + $perl .= <<""; +\$${field}_FieldID = JNI::GetFieldID(\$clazz, "$field", "$sig"); +sub $field (\$;\$) { + my \$self = shift; + if (\@_) { + JNI::SetObjectField(\$self, \$${field}_FieldID, + ref \$_[0] ? \$_[0] : JNI::NewStringUTF(\$_[0])); + } + else { + JNI::GetStringUTFChars(JNI::GetObjectField(\$self, \$${field}_FieldID)); + } +}\n + + } + } + else { + if ($staticfield{$field}) { + $perl .= <<""; +\$${field}_FieldID = JNI::GetStaticFieldID(\$clazz, "$field", "$sig"); +sub $field (\$;\$) { + my \$self = shift; + if (\@_) { + JNI::SetStaticObjectField(\$clazz, \$${field}_FieldID, \$_[0]); + } + else { + bless JNI::GetStaticObjectField(\$clazz, \$${field}_FieldID), "$pltype"; + } +}\n + + } + else { + $perl .= <<""; +\$${field}_FieldID = JNI::GetFieldID(\$clazz, "$field", "$sig"); +sub $field (\$;\$) { + my \$self = shift; + if (\@_) { + JNI::SetObjectField(\$self, \$${field}_FieldID, \$_[0]); + } + else { + bless JNI::GetObjectField(\$self, \$${field}_FieldID), "$pltype"; + } +}\n + + } + } + } + } + } + + $plname =~ s/^JPL::${class}:://; + + my $proto = '$' x (@jargs + 1); + $perl .= "sub $plname ($proto) {\n"; + $perl .= ' my ($self, '; + foreach my $jarg (@jargs) { + $perl .= "\$$jarg, "; + } + $perl =~ s/, $/) = \@_;\n/; + $perl .= <<"END"; + warn "JPL::${class}::$plname(\@_)\\n" if \$JPL::DEBUG; +#line $protos[$PROTO][3] "$jpfile" +$protos[$PROTO][2]} + +END + + $PERLLINE += $perl =~ tr/\n/\n/ + 2; + $perl .= <<"END"; +#line $PERLLINE "" +END + $PERLLINE--; + + $PERL .= $perl; + } + continue { + $PROTO++; + print "\n" if $DEBUG; + } + + emit_c_footer(); + + rename $cfile, "$cfile.old"; + rename "$cfile.new", $cfile; + + open(PLFILE, ">$plfile") or die "Can't create $plfile: $!\n"; + print PLFILE "BEGIN { \$JPL::_env_ ||= 1; } # suppress bogus embedding\n\n"; + if (%classseen) { + my @classes = sort keys %classseen; + print PLFILE "use JPL::Class qw(@classes);\n\n"; + } + print PLFILE $PERL; + print PLFILE "1;\n"; + close PLFILE; + + print "perl -c $plfile\n"; + system "perl -c $plfile" and die "jpl stopped\n"; +} + +sub emit_c_header { + open(CFILE, ">$cfile.new") or die "Can't create $cfile.new: $!\n"; + emit <<""; +!/* This file is automatically generated. Do not modify! */ +! +!#include "$hfile" +! +!#ifdef __cplusplus +!extern "C" { +!#endif +! +!#include "EXTERN.h" +!#include "perl.h" +! +!#ifdef __cplusplus +!} +!# define EXTERN_C extern "C" +!#else +!# define EXTERN_C extern +!#endif +! +!extern int jpldebug; +!extern JNIEnv* jplcurenv; +! + +} + + +sub emit_c_footer { + close CFILE; +} + +sub emit { + my $string = shift; + $string =~ s/^!//mg; + print CFILE $string; +} + +sub j2p_class { + my $jclass = shift; + $jclass =~ s#/#::#g; + $jclass; +} diff --git a/JPL/Makefile.PL b/JPL/Makefile.PL new file mode 100644 index 0000000..efb606d --- /dev/null +++ b/JPL/Makefile.PL @@ -0,0 +1,36 @@ +#!/usr/bin/perl + +$JPL_SRC = ".."; + +use Config; + +eval `$JPL_SRC/setvars -perl`; + +open(MAKEFILE, ">Makefile"); + +print MAKEFILE <<"SUBS"; +PERL = perl$] +ARCHNAME = $Config{archname} +JAVA_HOME = $ENV{JAVA_HOME} +JPL_HOME = $ENV{JPL_HOME} +PERLARCHDIR = $Config{archlib} + +SUBS + +print MAKEFILE <<'NOSUBS'; + +all: + +debug: + +test: + +install: + mkdir -p $(JPL_HOME)/perl/JPL + cp *.p[ml] $(JPL_HOME)/perl/JPL + +clean: + +NOSUBS + +close MAKEFILE; diff --git a/JPL_Rolo/JPL_Rolo.jpl b/JPL_Rolo/JPL_Rolo.jpl new file mode 100755 index 0000000..3c77fb2 --- /dev/null +++ b/JPL_Rolo/JPL_Rolo.jpl @@ -0,0 +1,553 @@ +import java.awt.*; +import java.awt.event.*; +import java.lang.*; +import java.util.*; + +public class JPL_Rolo extends Frame { + + // The primary key of the row that is current onscreen. + // + int current_row = 0; + + // TextField objects for each column. + // + TextField fld_name, fld_address, fld_city, fld_state, fld_zip, fld_id; + + // Add or Edit mode. + // + String edit_status; + + // a layout manager for the Frame + // + GridBagLayout gb = new GridBagLayout(); + + // Action buttons. + // + Button next, previous, quit, save, newrow, edit, cancel, delete; + + // A Panel for the action buttons. + // + Panel actionbuttons; + + /** + * Construct a new instance of JPL_Rolo. + */ + public JPL_Rolo(String[] argv) { + CreateForm(); + addWindowListener(new WinEventHandler() ); + } + + public void CreateForm() { + + // set the layout for the frame + // + this.setLayout(gb); + + // this is the offset within the GridBagLayout. If + // I want the next object on a different line, I + // postincrement. If not, I don't. + // + int i = 0; + + // Add a text field for the name. + // + AddToFrame(new Label("Name:"), 0, i); + fld_name = new TextField(20); + fld_name.setEditable(false); + AddToFrame(fld_name, 1, i++); + + // The address. + // + AddToFrame(new Label("Address:"), 0, i); + fld_address = new TextField(35); + fld_address.setEditable(false); + AddToFrame(fld_address, 1, i++); + + // The City. I'm not going to increment i, so the + // next field will show up on the same line. + // + AddToFrame(new Label("City:"), 0, i); + fld_city = new TextField(20); + fld_city.setEditable(false); + AddToFrame(fld_city, 1, i); + + // The State. + // + AddToFrame(new Label("State:"), 2, i); + fld_state = new TextField(2); + fld_state.setEditable(false); + AddToFrame(fld_state, 3, i++); + + // The Zip Code. + // + AddToFrame(new Label("Zip:"), 0, i); + fld_zip = new TextField(11); + fld_zip.setEditable(false); + AddToFrame(fld_zip, 1, i++); + + // The id - this is always read-only. + // + AddToFrame(new Label("Id:"), 0, i); + fld_id = new TextField(4); + fld_id.setEditable(false); + AddToFrame(fld_id, 1, i++); + + // create the button panel and give it a FlowLayout + // + actionbuttons = new Panel(); + actionbuttons.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5)); + + // Add the button panel to the Frame. The AddToFrame + // method isn't really set up to handle this sort of + // panel, so we will go through the tedious process + // of managing the GridBagConstraints... + // + GridBagConstraints c = new GridBagConstraints(); + c.gridwidth = 3; c.gridheight = 1; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.weightx = 0.0; c.weighty = 0.0; + c.gridx = 0; c.gridy = i; + ((GridBagLayout)this.getLayout()).setConstraints(actionbuttons, c); + this.add(actionbuttons); + + // instantiate and add each of the buttons + // + previous = new Button("Previous"); + actionbuttons.add(previous); + previous.addActionListener( new PrevRowHandler() ); + + next = new Button("Next"); + actionbuttons.add(next); + next.addActionListener( new NextRowHandler() ); + + quit = new Button("Quit"); + actionbuttons.add(quit); + quit.addActionListener( new QuitHandler() ); + + newrow = new Button("New"); + actionbuttons.add(newrow); + newrow.addActionListener( new NewRowHandler() ); + + edit = new Button("Edit"); + actionbuttons.add(edit); + edit.addActionListener( new EditRowHandler() ); + + delete = new Button("Delete"); + actionbuttons.add(delete); + delete.addActionListener( new DeleteRowHandler() ); + + // save and cancel are disabled until the user + // is adding or editing. + // + save = new Button("Save"); + actionbuttons.add(save); + save.setEnabled(false); + save.addActionListener( new SaveHandler() ); + + cancel = new Button("Cancel"); + actionbuttons.add(cancel); + cancel.setEnabled(false); + cancel.addActionListener( new CancelHandler() ); + + // Invoke getRow() to display the first row in the table. + // + getRow(0); + + } + + /** + * Return the id of the current row. + */ + public int getCurrentRowVal() { + return current_row; + } + + public void setCols(String name, String address, String city, String state, String zip, String id) { + + clearForm(); + + fld_name.setText(name); + fld_address.setText(address); + fld_city.setText(city); + fld_state.setText(state); + fld_zip.setText(zip); + fld_id.setText(id); + current_row = Integer.parseInt(id); + + } + + + public void setCurrentRow(int r) { + current_row = r; + } + + public String getName() { return fld_name.getText(); } + public String getAddress() { return fld_address.getText(); } + public String getCity() { return fld_city.getText(); } + public String getState() { return fld_state.getText(); } + public String getZip() { return fld_zip.getText(); } + public String getId() { return fld_id.getText(); } + + /** + * This eventhandler will move to the previous row. + */ + class PrevRowHandler implements ActionListener { + public void actionPerformed( ActionEvent e) { + getRow(-1); + } + } + + /** + * This eventhandler will move to the next row. + */ + class NextRowHandler implements ActionListener { + public void actionPerformed( ActionEvent e) { + getRow(1); + } + } + + /** + * This eventhandler will terminate the application. + */ + class QuitHandler implements ActionListener { + public void actionPerformed( ActionEvent e) { + System.exit(0); + } + } + + /** + * This eventhandler will display a blank record and put + * this application in new record mode. + */ + class NewRowHandler implements ActionListener { + public void actionPerformed( ActionEvent e) { + clearForm(); + edit_status = "new"; + setEdit(); + } + } + + /** + * This eventhandler will put the application in edit + * mode (for the current row). + */ + class EditRowHandler implements ActionListener { + public void actionPerformed( ActionEvent e) { + edit_status = "edit"; + setEdit(); + } + } + /** + * This eventhandler will delete the current row. + */ + class DeleteRowHandler implements ActionListener { + public void actionPerformed( ActionEvent e) { + delRow(); + } + } + + /** + * This eventhandler will save (update or insert) the + * current record. + */ + class SaveHandler implements ActionListener { + public void actionPerformed( ActionEvent e) { + + if (edit_status.equals("new")) { + saveIt(); + } + if (edit_status.equals("edit")) { + updateRow(); + } + + // set the edit_status to "browse", and call setBrowse() + // + edit_status = "browse"; + setBrowse(); + } + } + + /** + * This eventhandler cancels any pending edit. + */ + class CancelHandler implements ActionListener { + public void actionPerformed( ActionEvent e) { + // if it was new, make sure that they can't edit the + // id field... + + if (edit_status.equals("new")) { + fld_id.setEditable(false); + } + + // return the edit_status to browse, call getRow() + // to retrieve the row they were looking at + // before editing or adding, and call setBrowse() + // + edit_status = "browse"; + getRow(0); + setBrowse(); + } + } + + // This is the event handler to deal with cases where + // the user closes the window with a window control. + // + class WinEventHandler extends WindowAdapter { + public void windowClosing(WindowEvent e) { + System.exit(0); + } + } + + /** + * clearForm() + */ + protected void clearForm () { + fld_name.setText(""); + fld_address.setText(""); + fld_city.setText(""); + fld_state.setText(""); + fld_zip.setText(""); + fld_id.setText(""); + } + + /** + * AddToFrame() + * A convenience method to wrap the living hell + * that is GridBagConstraints() + */ + protected void AddToFrame (Component item, int x, int y) { + + // some sane layout defaults. + // + GridBagConstraints c = new GridBagConstraints(); + c.gridwidth = 1; c.gridheight = 1; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.NORTHWEST; + c.weightx = 0.0; c.weighty = 0.0; + + // set the grid coordinates + // + c.gridx = x; c.gridy = y; + + // set the constraints, and add the item to the layout + // + + ((GridBagLayout)this.getLayout()).setConstraints(item, c); + this.add(item); + } + + /** + * setEdit() + * + * prepare the form for editing/adding + */ + protected void setEdit () { + + // disable all these buttons + // + next.setEnabled(false); + previous.setEnabled(false); + newrow.setEnabled(false); + edit.setEnabled(false); + delete.setEnabled(false); + + // set everything except the id to be editable + // + fld_name.setEditable(true); + fld_address.setEditable(true); + fld_city.setEditable(true); + fld_state.setEditable(true); + fld_zip.setEditable(true); + + // enable these two buttons + // + save.setEnabled(true); + cancel.setEnabled(true); + } + + /** + * setBrowse() + * + * prepare the form for viewing + * + */ + protected void setBrowse() { + + // enable all these buttons + // + next.setEnabled(true); + previous.setEnabled(true); + newrow.setEnabled(true); + edit.setEnabled(true); + delete.setEnabled(true); + + // disable the fields + // + fld_name.setEditable(false); + fld_address.setEditable(false); + fld_city.setEditable(false); + fld_state.setEditable(false); + fld_zip.setEditable(false); + fld_id.setEditable(false); + + // disable these two buttons + // + save.setEnabled(false); + cancel.setEnabled(false); + } + + perl void delRow() {{ + + my $id = $self->getId____s(); + + $sql = qq[delete from cardfile ] . + qq[where (id = $id)]; + + use Sprite; + my $rdb = new Sprite(); + my @data = $rdb->sql($sql); + $rdb->close("cardfile"); + my $status = shift @data; + if (!$status) { + print STDERR "Bummer - couldn't execute query!\n"; + die; + } + $self->setCurrentRow__I(0); + $self->getRow__I(0); + + }} + + perl void updateRow() {{ + + my $name = $self->getName____s(); + my $address = $self->getAddress____s(); + my $city = $self->getCity____s(); + my $state = $self->getState____s(); + my $zip = $self->getZip____s(); + my $id = $self->getId____s(); + + $sql = qq[update cardfile ] . + qq[set name = ('$name'), ] . + qq[set address = ('$address'), ] . + qq[set city = ('$city'), ] . + qq[set state = ('$state'), ] . + qq[set zip = ('$zip') ] . + qq[where (id = $id)]; + + use Sprite; + my $rdb = new Sprite(); + my @data = $rdb->sql($sql); + $rdb->close("cardfile"); + my $status = shift @data; + if (!$status) { + print STDERR "Bummer - couldn't execute query!\n"; + die; + } + + }} + + + /** + * getRow() + * + * This method is used to either fetch this current row, + * in which case it is given an argument of zero, or it + * can be used to move relative to the current row, in + * which case it must be given an argument of 1 or -1. + * + */ + + + perl void getRow(int direction) {{ + + use Sprite; + my $rdb = new Sprite(); + + my $nextid = $self->getCurrentRowVal____I() + $direction; + my $op; + if ($direction == -1) { + $op = "<="; + } else { + $op = ">="; + } + my @data = $rdb->sql("select name, address, city, state, zip, id from cardfile where id $op $nextid"); + $rdb->close("cardfile"); + + my $status = shift @data; + if (!$status) { + print STDERR "Bummer - couldn't execute query!\n"; + die; + } + + my $numrows = scalar(@data); + + if (!$numrows) { + print STDERR "End of file reached.\n"; + return; + } + + my $index; + if ($direction == -1) { + $index = $#data; + } else { + $index = 0; + } + my($name, $address, $city, $state, $zip, $id) = split (/\0/, $data[$index], 6); + $self->setCols__ssssss($name, $address, $city, $state, $zip, $id); + + }} + + perl void saveIt() {{ + + use Sprite; + my $rdb = new Sprite(); + + my @data = $rdb->sql("select id, name from cardfile"); + + my $status = shift @data; + if (!$status) { + print STDERR "Bummer - couldn't execute query!\n"; + die; + } + + my @ids; + foreach $record (@data) { + my ($id, $name) = split (/\0/, $record, 2); + push @ids, $id; + } + @ids = sort @ids; + my $newid = $ids[$#ids] + 1; + + my $name = $self->getName____s(); + my $address = $self->getAddress____s(); + my $city = $self->getCity____s(); + my $state = $self->getState____s(); + my $zip = $self->getZip____s(); + + my $sql = "insert into cardfile (name, address, city, state, zip, id) values ('$name', '$address', '$city', '$state', '$zip', $newid)"; + @data = $rdb->sql($sql); + $rdb->close("cardfile"); + + $status = shift @data; + if (!$status) { + print STDERR "Bummer - couldn't execute insert!\n"; + die; + } + + $self->setCurrentRow__I($newid); + + }} + + public static void main(String[] args) { + + // make a new JPL_Rolo, pack() it and show() it. + JPL_Rolo cardfile = new JPL_Rolo(args); + cardfile.pack(); + cardfile.show(); + + } + +} + + diff --git a/JPL_Rolo/Makefile.PL b/JPL_Rolo/Makefile.PL new file mode 100644 index 0000000..3dd1f84 --- /dev/null +++ b/JPL_Rolo/Makefile.PL @@ -0,0 +1,84 @@ +#!/usr/bin/perl + +$JPL_HOME = $ENV{JPL_HOME} + or die "You have not run setvars to set your environment variables.\n" . + "See the JPL README file for more information.\n"; + +use Config; + +eval `$JPL_HOME/setvars -perl`; + +chop($WHAT = `pwd`); +$WHAT =~ s#.*/##; + +if ($^O eq 'linux') { + $flags = "-Dbool=char"; # avoid builtin bool altogether + $libs = "-lc -lm -ldl"; +} +else { + $flags = ""; + $libs = "-lc -lm -ldl"; +} +chop($cwd = `pwd`); +($jpldir = $cwd) =~ s#/[^/]*$##; + +open(MAKEFILE, ">Makefile"); + +print MAKEFILE <<"SUBS"; +CC = $Config{cc} +WHAT = $WHAT +PERL = perl$] +ARCHNAME = $Config{archname} +JAVA_HOME = $ENV{JAVA_HOME} +JPL_HOME = $ENV{JPL_HOME} +PERLARCHDIR = $Config{archlib} +FLAGS = $Config{cccdlflags} $Config{ccdlflags} $Config{lddlflags} $flags +INCL = -I\$(PERLARCHDIR)/CORE \\ + -I\$(JAVA_HOME)/include \\ + -I\$(JAVA_HOME)/include/$^O \\ + -I\$(JAVA_HOME)/include/genunix +LIBS = $libs + +SUBS + +print MAKEFILE <<'NOSUBS'; +.SUFFIXES: .jpl .class + +.jpl.class: + $(PERL) -MJPL::Compile -e "file('$*.jpl')" + +all: $(WHAT).class lib$(WHAT).so + +debug: $(WHAT)_g.class lib$(WHAT)_g.so + +lib$(WHAT).so: $(WHAT).c $(JPL_HOME)/lib/$(ARCHNAME)/libPerlInterpreter.so + $(CC) $(FLAGS) $(INCL) $(WHAT).c \ + $(PERLARCHDIR)/CORE/libperl.so \ + $(JPL_HOME)/lib/$(ARCHNAME)/libPerlInterpreter.so \ + $(LIBS) \ + -o lib$(WHAT).so + +lib$(WHAT)_g.so: $(WHAT).c $(JPL_HOME)/lib/$(ARCHNAME)/libPerlInterpreter_g.so + $(CC) -g $(FLAGS) $(INCL) $(WHAT).c \ + $(PERLARCHDIR)/CORE/libperl.so \ + $(JPL_HOME)/lib/$(ARCHNAME)/libPerlInterpreter_g.so \ + $(LIBS) \ + -o lib$(WHAT)_g.so + +test: + +install: all + cp $(WHAT).class $(JPL_HOME)/lib + cp lib$(WHAT).so $(JPL_HOME)/lib/$(ARCHNAME) + cp $(WHAT).pl $(JPL_HOME)/perl + +clean: + rm -f $(WHAT).c $(WHAT).h \ + $(WHAT)*.class $(WHAT)*.pl lib$(WHAT).so $(WHAT)*.java + +distclean: clean + rm -f Makefile + +NOSUBS + +close MAKEFILE; diff --git a/JPL_Rolo/README b/JPL_Rolo/README new file mode 100644 index 0000000..6d4b14b --- /dev/null +++ b/JPL_Rolo/README @@ -0,0 +1,27 @@ +Welcome to the Sprite sample application for Larry Wall's JPL. This +application showcases a merging of Java and Perl in which Java is employed +to generate a user interface, and Perl is used for data access. +Specifically, Perl is used with Shishir Gundavaram's Sprite module to offer +permanent storage through SQL manipulation of text files. This application +is a Rolodex(tm)-style address file, offering the ability to add, edit or +delete names and addresses. You may also navigate through the address list. + +To use this example, you will need to install the Sprite module from CPAN. + +To install the sample, you must first have JPL installed and working. +Please ensure that you have set environment variables as directed in the +JPL README and that the JPL Sample program works. Once this has been +accomplished, you can build the files in this directory with the following +commmands: + + perl Makefile.PL + make + make install + +You can run this by typing: + + java JPL_Rolo + +The application should appear with some sample data, and you can mess +around with it and put all your friends in the address book. Far out! + diff --git a/JPL_Rolo/cardfile b/JPL_Rolo/cardfile new file mode 100755 index 0000000..eecc806 --- /dev/null +++ b/JPL_Rolo/cardfile @@ -0,0 +1,7 @@ +name,address,city,state,zip,id +Brian Jepson,50 Hudson Street,Providence,RI,02909,100 +Elvis Presley,50 Hudson Street,Providence,RI,02909,101 +AS220,115 Empire Street,Providence,RI,02909,600 +Mr. Jones,100 Loudermilk Drive,Springfield,??,,602 +George Maciunas,Canal Street,New York,NY,????,603 +Emmett Williams,Broome Street,New York,NY,?????,605 diff --git a/PerlInterpreter/Makefile b/PerlInterpreter/Makefile new file mode 100644 index 0000000..a615fe1 --- /dev/null +++ b/PerlInterpreter/Makefile @@ -0,0 +1,43 @@ +WHAT = PerlInterpreter +JAVA_HOME = /usr/local/java +JPL_HOME = /usr/local/jpl +ARCHNAME = sun4-solaris +PERLARCHDIR = /usr/local/lib/perl5/sun4-solaris/5.00404 +CC = gcc +FLAGS = -fPIC -R /usr/local/lib/perl5/sun4-solaris/5.00404/CORE -G -L/usr/local/lib +INCL = -I$(PERLARCHDIR)/CORE \ + -I$(JAVA_HOME)/include \ + -I$(JAVA_HOME)/include/solaris \ + -I$(JAVA_HOME)/include/genunix +LIBS = -lc -lm -ldl + +.SUFFIXES: .java .class + +.java.class: + javac $*.java + +.class.h: + javah -jni $* + +all: PerlInterpreter.class libPerlInterpreter.so + +PerlInterpreter.class: PerlInterpreter.java + +PerlInterpreter.h: PerlInterpreter.class + +libPerlInterpreter.so: PerlInterpreter.c PerlInterpreter.h + $(CC) $(FLAGS) $(INCL) PerlInterpreter.c \ + $(PERLARCHDIR)/auto/DynaLoader/DynaLoader.a \ + $(LIBS) \ + -o libPerlInterpreter.so + +test: + +install: all + mkdir -p $(JPL_HOME)/lib/$(ARCHNAME) + cp libPerlInterpreter.so $(JPL_HOME)/lib/$(ARCHNAME) + cp $(WHAT).class $(JPL_HOME)/lib + +clean: + rm -f libPerlInterpreter.so + rm -f PerlInterpreter.class diff --git a/PerlInterpreter/Makefile.PL b/PerlInterpreter/Makefile.PL new file mode 100644 index 0000000..76852c6 --- /dev/null +++ b/PerlInterpreter/Makefile.PL @@ -0,0 +1,70 @@ +#!/usr/bin/perl + +$JPL_SRC = ".."; + +use Config; + +eval `$JPL_SRC/setvars -perl`; + +if ($^O eq 'linux') { + $flags = "-Dbool=char"; # avoid builtin bool altogether + $libs = "-lc -lm -ldl"; +} +else { + $flags = ""; + $libs = "-lc -lm -ldl"; +} + +open(MAKEFILE, ">Makefile"); + +print MAKEFILE <<"SUBS"; +WHAT = PerlInterpreter +JAVA_HOME = $ENV{JAVA_HOME} +JPL_HOME = $ENV{JPL_HOME} +ARCHNAME = $Config{archname} +PERLARCHDIR = $Config{archlib} +CC = $Config{cc} +FLAGS = $Config{cccdlflags} $Config{ccdlflags} $Config{lddlflags} $flags +INCL = -I\$(PERLARCHDIR)/CORE \\ + -I\$(JAVA_HOME)/include \\ + -I\$(JAVA_HOME)/include/$^O \\ + -I\$(JAVA_HOME)/include/genunix +LIBS = $libs + +SUBS + + +print MAKEFILE <<'NOSUBS'; +.SUFFIXES: .java .class + +.java.class: + javac $*.java + +.class.h: + javah -jni $* + +all: PerlInterpreter.class libPerlInterpreter.so + +PerlInterpreter.class: PerlInterpreter.java + +PerlInterpreter.h: PerlInterpreter.class + +libPerlInterpreter.so: PerlInterpreter.c PerlInterpreter.h + $(CC) $(FLAGS) $(INCL) PerlInterpreter.c \ + $(PERLARCHDIR)/auto/DynaLoader/DynaLoader.a \ + $(LIBS) \ + -o libPerlInterpreter.so + +test: + +install: all + mkdir -p $(JPL_HOME)/lib/$(ARCHNAME) + cp libPerlInterpreter.so $(JPL_HOME)/lib/$(ARCHNAME) + cp $(WHAT).class $(JPL_HOME)/lib + +clean: + rm -f libPerlInterpreter.so + rm -f PerlInterpreter.class +NOSUBS + +close MAKEFILE; diff --git a/PerlInterpreter/PerlInterpreter.c b/PerlInterpreter/PerlInterpreter.c new file mode 100644 index 0000000..29a275e --- /dev/null +++ b/PerlInterpreter/PerlInterpreter.c @@ -0,0 +1,132 @@ +/* + * "The Road goes ever on and on, down from the door where it began." + */ + +#include "PerlInterpreter.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#include "EXTERN.h" +#include "perl.h" + +#ifdef __cplusplus +} +# define EXTERN_C extern "C" +#else +# define EXTERN_C extern +#endif + +static void xs_init _((void)); +static PerlInterpreter *my_perl; + +int jpldebug = 0; +JNIEnv *jplcurenv; + +JNIEXPORT void JNICALL +Java_PerlInterpreter_init(JNIEnv *env, jobject obj, jstring js) +{ + int exitstatus; + int argc = 3; + SV* envsv; + SV* objsv; + + static char *argv[] = {"perl", "-e", "1", 0}; + + if (getenv("JPLDEBUG")) + jpldebug = atoi(getenv("JPLDEBUG")); + + if (jpldebug) + fprintf(stderr, "init\n"); + + if (!dlopen("libperl.so", RTLD_LAZY|RTLD_GLOBAL)) { + fprintf(stderr, "%s\n", dlerror()); + exit(1); + } + + if (curinterp) + return; + + perl_init_i18nl10n(1); + + if (!do_undump) { + my_perl = perl_alloc(); + if (!my_perl) + exit(1); + perl_construct( my_perl ); + perl_destruct_level = 0; + } + + exitstatus = perl_parse( my_perl, xs_init, argc, argv, (char **) NULL ); + + if (!exitstatus) + Java_PerlInterpreter_eval(env, obj, js); + +} + +JNIEXPORT void JNICALL +Java_PerlInterpreter_eval(JNIEnv *env, jobject obj, jstring js) +{ + SV* envsv; + SV* objsv; + dSP; + jbyte* jb; + + ENTER; + SAVETMPS; + + jplcurenv = env; + envsv = perl_get_sv("JPL::_env_", 1); + sv_setiv(envsv, (IV)(void*)env); + objsv = perl_get_sv("JPL::_obj_", 1); + sv_setiv(objsv, (IV)(void*)obj); + + jb = (jbyte*)(*env)->GetStringUTFChars(env,js,0); + + if (jpldebug) + fprintf(stderr, "eval %s\n", (char*)jb); + + perl_eval_pv( (char*)jb, 0 ); + + if (SvTRUE(GvSV(errgv))) { + jthrowable newExcCls; + + (*env)->ExceptionDescribe(env); + (*env)->ExceptionClear(env); + + newExcCls = (*env)->FindClass(env, "java/lang/RuntimeException"); + if (newExcCls) + (*env)->ThrowNew(env, newExcCls, SvPV(GvSV(errgv),na)); + } + + (*env)->ReleaseStringUTFChars(env,js,jb); + FREETMPS; + LEAVE; + +} + +/* +JNIEXPORT jint JNICALL +Java_PerlInterpreter_eval(JNIEnv *env, jobject obj, jint ji) +{ + op = (OP*)(void*)ji; + op = (*op->op_ppaddr)(); + return (jint)(void*)op; +} +*/ + +/* Register any extra external extensions */ + +/* Do not delete this line--writemain depends on it */ +EXTERN_C void boot_DynaLoader _((CV* cv)); +EXTERN_C void boot_JNI _((CV* cv)); + +static void +xs_init() +{ + char *file = __FILE__; + dXSUB_SYS; + newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file); +} diff --git a/PerlInterpreter/PerlInterpreter.h b/PerlInterpreter/PerlInterpreter.h new file mode 100644 index 0000000..22fdf52 --- /dev/null +++ b/PerlInterpreter/PerlInterpreter.h @@ -0,0 +1,29 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class PerlInterpreter */ + +#ifndef _Included_PerlInterpreter +#define _Included_PerlInterpreter +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: PerlInterpreter + * Method: init + * Signature: (Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_PerlInterpreter_init + (JNIEnv *, jobject, jstring); + +/* + * Class: PerlInterpreter + * Method: eval + * Signature: (Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_PerlInterpreter_eval + (JNIEnv *, jobject, jstring); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/PerlInterpreter/PerlInterpreter.java b/PerlInterpreter/PerlInterpreter.java new file mode 100644 index 0000000..c26a4f2 --- /dev/null +++ b/PerlInterpreter/PerlInterpreter.java @@ -0,0 +1,21 @@ +class PerlInterpreter { + static boolean initted = false; + + public native void init(String s); + public native void eval(String s); + +// public native long op(long i); + + public PerlInterpreter fetch () { + if (!initted) { + init("$JPL::DEBUG = $ENV{JPLDEBUG}"); + initted = true; + } + return this; + } + + static { + System.loadLibrary("PerlInterpreter"); + } +} + diff --git a/README b/README new file mode 100644 index 0000000..ae23b4b --- /dev/null +++ b/README @@ -0,0 +1,77 @@ +Copyright 1998, O'Reilly & Associates, Inc. + +This package may be copied under the same terms as Perl itself. + +Disclaimers +----------- +This is a work in progress, and relies on bleeding-edge technology +from the network. Don't expect not to be surprised occasionally. + +Requirements +------------ +Perl 5.004 (or later) must be compiled and installed as a shared library +(libperl.so). I had to use the system's malloc. We've tested +it most heavily with 5.004_04. + +You need JDK 1.1. On Solaris 1.1.1 works. On Linux you need 1.1.3 with +the patches from + + ftp://ftp.blackdown.org/pub/Linux/JDK/1.1.3/updates/libjava-1.1.3v2-1.tar.gz + +The get_jdk directory contains a script that will download JDK (but not +the patch file above) off of the net for you. (This presumes you've +already installed the modules mentioned in ../README.) + +What the heck is JPL? +--------------------- +JPL is a hybrid (to use the polite term) language. It's basically Java +in which the methods can optionally be implemented by Perl code. A +preprocessor called "JPL::Compile" looks at your .jpl file and spits +out the appropriate .java, .c, .h, .pl, and .so files to accomplish the +desired task. Hopefully a lot of those files can go away in the future +as jpl mutates into a Perl-to-Java compiler. The long-term goal is for +jpl to be able to take a pure Perl file and spit out a java .class +file. This initial version of JPL is an attempt to begin to mesh the +semantics of Java and Perl. Some people may find it useful in its +current form, but you should know right up front that we've still got a +ways to go with it. A journey of a thousand miles continues with the +second step... + +JPL Syntax +---------- +JPL syntax is trivial, given that you know Java and Perl. Pretend like +you're writing a native Java method, but say "perl" instead of +"native", and then instead of omitting the body of the method, put your +Perl code in double curlies. (See Sample.jpl for an example.) + +Calling back from Perl to Java is done through the JNI (Java Native +Interface). No weird transmogrifications are done by the preprocessor +to your Perl code--it's all normal Perl. The preprocessor just wraps +it up into funny subroutines you don't see unless you peek at the .pl +file it generates. + +Installation +------------ +Run "install-jpl". You have to tell it whether you want to use the +current directory for JPL_HOME or some other directory. Everything +else should take care of itself, except that after install-jpl +write the setvars program, you are responsible to invoke it properly +before any JPL applications can be compiled under the current shell. + + sh: eval `setvars -sh` + csh: eval `setvars -csh` + perl: eval `setvars -perl`; + +More Info +--------- + +You can look at the Sample and Test directories, as well as the ../eg +directory for examples. + +Perhaps the most important bit of advice we can give you is to watch + + http://perl.oreilly.com + +for further information on how to get further information. + +Have the appropriate amount of fun. diff --git a/Sample/Makefile.PL b/Sample/Makefile.PL new file mode 100644 index 0000000..944c7e1 --- /dev/null +++ b/Sample/Makefile.PL @@ -0,0 +1,84 @@ +#!/usr/bin/perl + +$JPL_HOME = $ENV{JPL_HOME} + or die "You have not run setvars to set your environment variables.\n" . + "See the JPL README file for more information.\n"; + +use Config; + +eval `$JPL_HOME/setvars -perl`; + +chop($WHAT = `pwd`); +$WHAT =~ s#.*/##; + +if ($^O eq 'linux') { + $flags = "-Dbool=char"; # avoid builtin bool altogether + $libs = "-lc -lm -ldl"; +} +else { + $flags = ""; + $libs = "-lc -lm -ldl"; +} +chop($cwd = `pwd`); +($jpldir = $cwd) =~ s#/[^/]*$##; + +open(MAKEFILE, ">Makefile"); + +print MAKEFILE <<"SUBS"; +CC = $Config{cc} +WHAT = $WHAT +PERL = perl$] +ARCHNAME = $Config{archname} +JAVA_HOME = $ENV{JAVA_HOME} +JPL_HOME = $ENV{JPL_HOME} +PERLARCHDIR = $Config{archlib} +FLAGS = $Config{cccdlflags} $Config{ccdlflags} $Config{lddlflags} $flags +INCL = -I\$(PERLARCHDIR)/CORE \\ + -I\$(JAVA_HOME)/include \\ + -I\$(JAVA_HOME)/include/$^O \\ + -I\$(JAVA_HOME)/include/genunix +LIBS = $libs + +SUBS + +print MAKEFILE <<'NOSUBS'; +.SUFFIXES: .jpl .class + +.jpl.class: + $(PERL) -MJPL::Compile -e "file('$*.jpl')" + +all: $(WHAT).class lib$(WHAT).so + +debug: $(WHAT)_g.class lib$(WHAT)_g.so + +lib$(WHAT).so: $(WHAT).c $(JPL_HOME)/lib/$(ARCHNAME)/libPerlInterpreter.so + $(CC) $(FLAGS) $(INCL) $(WHAT).c \ + $(PERLARCHDIR)/CORE/libperl.so \ + $(JPL_HOME)/lib/$(ARCHNAME)/libPerlInterpreter.so \ + $(LIBS) \ + -o lib$(WHAT).so + +lib$(WHAT)_g.so: $(WHAT).c $(JPL_HOME)/lib/$(ARCHNAME)/libPerlInterpreter_g.so + $(CC) -g $(FLAGS) $(INCL) $(WHAT).c \ + $(PERLARCHDIR)/CORE/libperl.so \ + $(JPL_HOME)/lib/$(ARCHNAME)/libPerlInterpreter_g.so \ + $(LIBS) \ + -o lib$(WHAT)_g.so + +test: + +install: all + cp *.class $(JPL_HOME)/lib + cp lib$(WHAT).so $(JPL_HOME)/lib/$(ARCHNAME) + cp $(WHAT).pl $(JPL_HOME)/perl + +clean: + rm -f $(WHAT).c $(WHAT).h \ + $(WHAT)*.class $(WHAT)*.pl lib$(WHAT).so $(WHAT)*.java + +distclean: clean + rm -f Makefile + +NOSUBS + +close MAKEFILE; diff --git a/Sample/Sample.jpl b/Sample/Sample.jpl new file mode 100644 index 0000000..a095201 --- /dev/null +++ b/Sample/Sample.jpl @@ -0,0 +1,48 @@ +class Sample { + public static void main(String[] args) { + Sample sam = new Sample(); + System.out.println(sam.foo("manny","moe","jack")); + System.out.println(sam.foo(1)); + System.out.println(sam.foo(3.0)); + sam.foo(); + } + + public static int thrice(int i) { + return i * 3; + } + + perl void foo() {{ + use POSIX; + print "TZ = ", POSIX::tzname(), "\n"; + print "Got to ${self}->foo() method\n"; + print "foo__I(2) = ", $self->foo__I__I(2),"\n"; + print "thrice(123) = ", JPL::Sample->thrice__I__I(123), "\n"; + print "thrice(12) = ", JPL::Sample->thrice__I__I(12), "\n"; + print $self->foo__sss__s("MANNY", "MOE", "JACK"), "\n"; + print 41 + $self->foo__sss__s("1", "2", "3"), "\n"; + print "Perl version is $]\n"; + }} + + perl int foo(int a) {{ + $a + $a; + }} + + perl double foo(double a) {{ + use JPL::Class 'java::util::Random'; + $rng = java::util::Random->new(); + print "RNG = $rng\n"; + print $rng->nextDouble____D(), "\n"; + print $rng->nextDouble____D(), "\n"; + print $rng->nextDouble____D(), "\n"; + print $rng->nextDouble____D(), "\n"; + return $a * $a; + }} + + perl String foo( String a, + String b, + String c ) {{ + print "a = $a, b = $b, c = $c\n"; + join "+", $a, $b, $c; + }} + +} diff --git a/Test/Makefile.PL b/Test/Makefile.PL new file mode 100644 index 0000000..3dd1f84 --- /dev/null +++ b/Test/Makefile.PL @@ -0,0 +1,84 @@ +#!/usr/bin/perl + +$JPL_HOME = $ENV{JPL_HOME} + or die "You have not run setvars to set your environment variables.\n" . + "See the JPL README file for more information.\n"; + +use Config; + +eval `$JPL_HOME/setvars -perl`; + +chop($WHAT = `pwd`); +$WHAT =~ s#.*/##; + +if ($^O eq 'linux') { + $flags = "-Dbool=char"; # avoid builtin bool altogether + $libs = "-lc -lm -ldl"; +} +else { + $flags = ""; + $libs = "-lc -lm -ldl"; +} +chop($cwd = `pwd`); +($jpldir = $cwd) =~ s#/[^/]*$##; + +open(MAKEFILE, ">Makefile"); + +print MAKEFILE <<"SUBS"; +CC = $Config{cc} +WHAT = $WHAT +PERL = perl$] +ARCHNAME = $Config{archname} +JAVA_HOME = $ENV{JAVA_HOME} +JPL_HOME = $ENV{JPL_HOME} +PERLARCHDIR = $Config{archlib} +FLAGS = $Config{cccdlflags} $Config{ccdlflags} $Config{lddlflags} $flags +INCL = -I\$(PERLARCHDIR)/CORE \\ + -I\$(JAVA_HOME)/include \\ + -I\$(JAVA_HOME)/include/$^O \\ + -I\$(JAVA_HOME)/include/genunix +LIBS = $libs + +SUBS + +print MAKEFILE <<'NOSUBS'; +.SUFFIXES: .jpl .class + +.jpl.class: + $(PERL) -MJPL::Compile -e "file('$*.jpl')" + +all: $(WHAT).class lib$(WHAT).so + +debug: $(WHAT)_g.class lib$(WHAT)_g.so + +lib$(WHAT).so: $(WHAT).c $(JPL_HOME)/lib/$(ARCHNAME)/libPerlInterpreter.so + $(CC) $(FLAGS) $(INCL) $(WHAT).c \ + $(PERLARCHDIR)/CORE/libperl.so \ + $(JPL_HOME)/lib/$(ARCHNAME)/libPerlInterpreter.so \ + $(LIBS) \ + -o lib$(WHAT).so + +lib$(WHAT)_g.so: $(WHAT).c $(JPL_HOME)/lib/$(ARCHNAME)/libPerlInterpreter_g.so + $(CC) -g $(FLAGS) $(INCL) $(WHAT).c \ + $(PERLARCHDIR)/CORE/libperl.so \ + $(JPL_HOME)/lib/$(ARCHNAME)/libPerlInterpreter_g.so \ + $(LIBS) \ + -o lib$(WHAT)_g.so + +test: + +install: all + cp $(WHAT).class $(JPL_HOME)/lib + cp lib$(WHAT).so $(JPL_HOME)/lib/$(ARCHNAME) + cp $(WHAT).pl $(JPL_HOME)/perl + +clean: + rm -f $(WHAT).c $(WHAT).h \ + $(WHAT)*.class $(WHAT)*.pl lib$(WHAT).so $(WHAT)*.java + +distclean: clean + rm -f Makefile + +NOSUBS + +close MAKEFILE; diff --git a/Test/Test.jpl b/Test/Test.jpl new file mode 100644 index 0000000..ab6a1ce --- /dev/null +++ b/Test/Test.jpl @@ -0,0 +1,122 @@ +import java.util.*; + +public class Test { + + int myint = 123; + double mydouble = 3.14159265; + String mystring = "my string"; + static String ourstring = "our string"; + static boolean embedded = false; + int array[] = {1,2,3}; + Vector v; + + public Test() { + + + v = new Vector(); + v.addElement("Hello"); + printfields(); + Vector x = perlTryVec(v); + x.addElement("World"); + Vector y = perlTryVec(x); + if (!embedded) System.err.println("Thank you, perlTryVec!"); + + if (!embedded) System.err.println(retchars()); + if (!embedded) System.err.println("Thank you, retchars!"); + + String[] s = retstrings(); + if (!embedded) System.err.println(s[0] + s[1] + s[2] + s[3]); + if (!embedded) System.err.println("Thank you, retstrings!"); + + Object[] o = retobjects(v, x, y); + if (!embedded) System.err.println(o[1]); + if (!embedded) System.err.println(o[3]); + if (!embedded) System.err.println(o[4]); + if (!embedded) System.err.println("Thank you, retobjects!"); + + passarray(s); + + if (!embedded) System.err.println(s[0] + s[1] + s[2] + s[3]); + if (!embedded) System.err.println("Thank you, passarray!"); + + printfields(); + if (!embedded) System.err.println("Thank you, printfields!"); + setfields(); + if (!embedded) System.err.println("Thank you, setfields!"); + printfields(); + if (!embedded) System.err.println("Thank you, printfields!"); + } + + perl Vector perlTryVec(Vector v) throws RuntimeException {{ + print "v is: $v\n"; + print "v isa: ", ref $v,"\n"; + + print "In perlTryVec() - Vector size is: ", $v->size([],['int']), "\n"; + @foo = times; + $size ||= getmeth('size', [], ['int']); + for ($i = 10000; $i; --$i) { + $x = $v->$size(); + } + @bar = times; + printf "%5.2fu %5.2fs\n", $bar[0] - $foo[0], $bar[1] - $foo[1]; + return $v; + }} + + perl char[] retchars() {{ + print "In retchars()\n"; + return [65,66,67]; + }} + + perl String[] retstrings() {{ + print "In retstrings()\n"; + return [1,2,3,"many"]; + }} + + perl Object[] retobjects(Vector v, Vector x, Vector y) {{ + print "In retstrings()\n"; + return [$v, $x, $y, "this is only a test", 123]; + }} + + perl void passarray(String[] s) {{ + print "In passarray()\n"; + print "s = $s\n"; + $t = GetObjectArrayElement($s,3); + print "t = $t\n"; + $x = GetStringUTFChars($t); + print "$x\n"; + $t = SetObjectArrayElement($s,3,NewStringUTF("infinity")); + }} + + perl void printfields() {{ + + $| = 1; + eval {print $self->v->toString____s(), "\n";}; + print $@ if $@; + + print $self->myint, "\n"; + print $self->mydouble, "\n"; + print $self->mystring, "\n"; + print JPL::Test->ourstring, "\n"; + + @nums = GetIntArrayElements($self->array()); + print "@nums\n"; + + @nums = unpack("i*", scalar GetIntArrayElements($self->array())); + print "@nums\n"; + }} + + perl void setfields() {{ + $self->myint(321); + $self->mydouble(2.7182918); + $self->mystring("MY STRING!!!"); + JPL::Test->ourstring("OUR STRING!!!"); + }} + + public static void main(String[] argv) { + if (java.lang.reflect.Array.getLength(argv) > 0 && + argv[0].equals("-nothanks")) + embedded = true; + Test f = new Test(); + if (!embedded) System.err.println("Thank you, Test!"); + } +} diff --git a/bin/jpl b/bin/jpl new file mode 120000 index 0000000..b52049e --- /dev/null +++ b/bin/jpl @@ -0,0 +1 @@ +../JPL/Compile.pm \ No newline at end of file diff --git a/get_jdk/README b/get_jdk/README new file mode 100644 index 0000000..0c38ccf --- /dev/null +++ b/get_jdk/README @@ -0,0 +1,74 @@ + +This archive contains the following files: +README - the README file which explains how to use this program (this file) +get_jdk.pl - the program to download JDK +jdk_hosts - the descriptor file required by the program + +Nate Patwardhan (nvp@oreilly.com) wrote get_jdk.pl to automate the +download of JDK (Java Development Kit) from a distribution site based +on your Unix flavor. This program is based on some of the examples +found in the LWP cookbook that was included with your LWP distribution. + +Current Unix flavors that appear in the descriptor file (more +suggestions from Beta testers will be welcomed): + Solaris + Linux + FreeBSD + +To use get_jdk.pl properly, you *must* have LWP (libwww) and its +dependencies installed. Once you've installed LWP, you should be able +to use this module without any problems on any Unix flavor. + +By default, get_jdk.pl uses #!/usr/local/bin/perl in its shebang path, +so you may have to execute get_jdk.pl like: + + perl get_jdk.pl + +-OR- + + perl5 get_jdk.pl + +based on your site's Perl installation. + +get_jdk.pl reads the $^O to determine what Unix flavor you're using, +and compares the value of $^O to the first field shown in the +descriptor file, jdk_hosts. For example, $^O for Solaris versions of +Perl is: 'solaris'; Solaris is represented in the descriptor file +like: + + solaris=>ftp://ftp.javasoft.com/pub/jdk1.1/jdk1.1.3-solaris2-sparc.bin + +When get_jdk.pl reads the descriptor file, it splits the fields on +'=>', and reads them into a hash, %HOSTS. get_jdk.pl then compares +the value of $^O to $HOSTS{'osname'}, and returns the address of the +JDK distribution site if $^O eq $HOSTS{'osname'}. If there is not a +match, get_jdk.pl fails. + +get_jdk.pl represents the hostname of distribution sites in URL +format: protocol://hostname.some.com/path/filename.extension +When a URL is found, get_jdk.pl parses out the filename; this is +significant, because the output from the remote host is directed to +the file parsed from the URL. + +When you execute get_jdk.pl, you'll know it's working correctly if it +outputs something like: + + A JDK port for your OS has been found. + Contacting: + ftp://ftp.javasoft.com/pub/jdk1.1/jdk1.1.3-solaris2-sparc.bin + Attempting to download: jdk1.1.3-solaris2-sparc.bin + 0% - 1460 bytes received + 0% - 4380 bytes received + 0% - 7300 bytes received + 0% - 8192 bytes received + [etc etc etc until you reach 100%] + +Future (PRK release) versions of get_jdk.pl will allow the user to +update the descriptor file from the ora.com (oreilly.com) FTP/WWW +site. This version does not support the -update flag. + +Happy JDK'ing! :-) + +-- +Nate Patwardhan +nvp@oreilly.com diff --git a/get_jdk/get_jdk.pl b/get_jdk/get_jdk.pl new file mode 100755 index 0000000..d6d399d --- /dev/null +++ b/get_jdk/get_jdk.pl @@ -0,0 +1,71 @@ +#!/usr/bin/perl -w + +# Based on an ftp client found in the LWP Cookbook and +# revised by Nathan V. Patwardhan . + +# Copyright 1997 O'Reilly and Associates +# This package may be copied under the same terms as Perl itself. +# +# Code appears in the Unix version of the Perl Resource Kit + +use LWP::UserAgent; +use URI::URL; + +my $ua = new LWP::UserAgent; + +# check to see if a JDK port exists for the OS. i'd say +# that we should use solaris by default, but a 9meg tarfile +# is a hard pill to swallow if it won't work for somebody. :-) +my $os_type = $^O; my $URL = lookup_jdk_port($os_type); +die("No JDK port found. Contact your vendor for details. Exiting.\n") + if $URL eq ''; + +print "A JDK port for your OS has been found.\nContacting: ".$URL."\n"; + +# Now, parse the URL using URI::URL +my($jdk_file) = (url($URL)->crack)[5]; +$jdk_file =~ /(.+)\/(.+)/; $jdk_file = $2; + +print "Attempting to download: $jdk_file\n"; + +my $expected_length; +my $bytes_received = 0; + +open(OUT, ">".$jdk_file) or die("Can't open $jdk_file: $!"); +$ua->request(HTTP::Request->new('GET', $URL), + sub { + my($chunk, $res) = @_; + + $bytes_received += length($chunk); + unless (defined $expected_length) { + $expected_length = $res->content_length || 0; + } + if ($expected_length) { + printf STDERR "%d%% - ", + 100 * $bytes_received / $expected_length; + } + print STDERR "$bytes_received bytes received\n"; + + print OUT $chunk; + } +); +close(OUT); + +sub lookup_jdk_port { + my($port_os) = @_; + my $jdk_hosts = 'jdk_hosts'; + my %HOSTS = (); + + open(CFG, $jdk_hosts) or die("hosts error: $!"); + while() { + chop; + ($os, $host) = split(/\s*=>\s*/, $_); + next unless $os eq $port_os; + push(@HOSTS, $host); + } + close(CFG); + + return "" unless @HOSTS; + return $HOSTS[rand @HOSTS]; # Pick one at random. +} + diff --git a/get_jdk/jdk_hosts b/get_jdk/jdk_hosts new file mode 100644 index 0000000..fa50b51 --- /dev/null +++ b/get_jdk/jdk_hosts @@ -0,0 +1,4 @@ +solaris => ftp://ftp.javasoft.com/pub/jdk1.1/jdk1.1.3-solaris2-sparc.bin +linux => ftp://ftp.infomagic.com/pub/mirrors/linux/Java/JDK-1.1.3/linux-jdk.1.1.3-v2.tar.gz +linux => ftp://ftp.connectnet.com/pub/java/JDK-1.1.3/linux-jdk.1.1.3-v2.tar.gz +freebsd => http://www.csi.uottawa.ca/~kwhite/jdkbinaries/jdk1.1-FreeBSD.tar.gz diff --git a/install-jpl b/install-jpl new file mode 100755 index 0000000..546ae91 --- /dev/null +++ b/install-jpl @@ -0,0 +1,229 @@ +#!/usr/bin/perl + +print <<'END' if $>; +NOTE: Since you're not running as root, the installation will su at +the appropriate time later. You will need to supply the root password +for the su program. + +END + +# Gather data. + +# JPL_SRC + +chop($JPL_SRC = `pwd`); +print "JPL_SRC = $JPL_SRC\n"; + +# JAVA_HOME + +foreach $dir ( + $ENV{JAVA_HOME}, + "/usr/java", + "/usr/local/java", + "/usr/lib/java", + "/usr/local/lib/java", +) { + $JAVA_HOME = $dir, last if $dir and -d "$dir/bin"; +} +die "You must set the \$JAVA_HOME environment variable first.\n" + unless $JAVA_HOME; +print "JAVA_HOME = $JAVA_HOME\n"; + +# JPL_HOME + +($likelyjpl = $JAVA_HOME) =~ s#(.*)/.*#$1/jpl#; + +print <<"END"; + +You need to decide which directory JPL files are to be installed in. +Applications will look in subdirectories of this directory for any JPL +related files. + +You may use the current directory ($JPL_SRC) +or you may use a directory such as $likelyjpl. + +END + +$| = 1; +until (-d $JPL_HOME) { + print "Install JPL files where: [$JPL_SRC] "; + chop($JPL_HOME = ); + $JPL_HOME ||= $JPL_SRC; + unless (-d $JPL_HOME) { + print "Warning: $JPL_HOME doesn't exist yet!\n\n"; + print "Do you want to create it? [y] "; + chop($ans = ); + $ans ||= 'y'; + next unless $ans =~ /^y/i; + + system "mkdir -p $JPL_HOME"; + if ($> and not -d $JPL_HOME) { + warn "Couldn't create $JPL_HOME!\nTrying again as root...running su...\n"; + system "set -x +su root -c 'mkdir -p $JPL_HOME && chown $> $JPL_HOME && chmod 0755 $JPL_HOME'"; + warn "Couldn't create $JPL_HOME!\n" unless -d $JPL_HOME; + } + } +} +print "JPL_HOME = $JPL_HOME\n"; + +######################################################################### +# Spit out setvars. + +print "Writing setvars...\n"; + +unlink "$JPL_SRC/setvars"; +open(SETVARS, ">$JPL_HOME/setvars") or die "Can't create setvars: $!\n"; +while () { + s/^JPL_SRC=.*/JPL_SRC='$JPL_SRC'/; + s/^JAVA_HOME=.*/JAVA_HOME='$JAVA_HOME'/; + s/^JPL_HOME=.*/JPL_HOME='$JPL_HOME'/; + print SETVARS $_; +} +close SETVARS; +chmod 0755, "$JPL_HOME/setvars"; +symlink "$JPL_HOME/setvars", "$JPL_SRC/setvars" if $JPL_HOME ne $JPL_SRC; + +######################################################################### +# Pretend we're make. + +eval `./setvars -perl`; # Take our own medicine. + +print "\n\nStarting install...\n"; + +system <<'END' and die "Couldn't install JPL\n"; +set -x +cd JPL +perl Makefile.PL +make clean +perl Makefile.PL +make install +END + +print "\nInstalling PerlInterpreter class\n"; + +system <<'END' and die "Couldn't install PerlInterpreter\n"; +set -x +cd PerlInterpreter +perl Makefile.PL +make clean +perl Makefile.PL +make install +END + +print "\nInstalling JNI module\n"; + +system <<'END' and die "Couldn't install JNI\n"; +set -x +cd JNI +perl Makefile.PL +make clean +perl Makefile.PL +make +echo 'Attempting to install JNI as root' +su root -c "make install" +END + +#touch Makefile +#make -f makefile.jv +## These should be executed as root +#rm -rf /usr/lib/perl5/site_perl/i586-linux/auto/JNI +#rm -rf /usr/lib/perl5/site_perl/auto/JNI +#rm -f /usr/lib/perl5/site_perl/JNI.pm +#make -f makefile.jv install UNINST=1 + +print "\nInstalling Sample JPL program\n"; + +system <<'END' and die "Couldn't install Sample\n"; +set -x +cd Sample +perl Makefile.PL +make clean +perl Makefile.PL +make install +END + +# Test +print "\n\nTesting Sample...\n"; +system <<'END' and die "Couldn't run Sample\n"; +set -x +cd Sample +JPLDEBUG=1 +export JPLDEBUG +java Sample +END + +__END__ +#!/bin/sh + +# You can edit this, but your changes will only last until the next +# time you run install-jpl. + +# Where jpl is currently installed + +cd `dirname $0` +JPL_SRC=`pwd` + +# Where java is installed + +JAVA_HOME=/usr/local/java +export JAVA_HOME + +# Where jpl will be installed + +JPL_HOME="$JPL_SRC" +export JPL_HOME + +# Which perl to run + +JPLPERL=perl`perl -e "print $]"` +#JPLPERL=perl5.00404 +export JPLPERL + +# Some derivative variables +archname=`$JPLPERL -MConfig -e 'print $Config{archname}'` + archlib=`$JPLPERL -MConfig -e 'print $Config{archlib}'` + +CLASSPATH=".:$JPL_HOME/lib${CLASSPATH:+:$CLASSPATH}" +export CLASSPATH + +LD_LIBRARY_PATH=".:$JPL_HOME/lib/$archname:$archlib/CORE${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" +export LD_LIBRARY_PATH + +PERL5LIB="$JPL_HOME/perl${PERL5LIB:+:$PERL5LIB}" +export PERL5LIB + +# Make sure the right java programs are selected. +PATH="$JAVA_HOME/bin:$PATH" +export PATH + +case "$1" in +-perl) + cat <