#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#ifdef __CYGWIN__
#include "w32api/basetyps.h"
#endif
#include "jni.h"
void
throw_ije(JNIEnv *env,
char
*msg){
jclass ije ;
ije = (*(env))->FindClass(env,
"org/perl/inline/java/InlineJavaException"
) ;
if
((*(env))->ExceptionCheck(env)){
(*(env))->ExceptionDescribe(env) ;
(*(env))->ExceptionClear(env) ;
(*(env))->FatalError(env,
"Can't find class InlineJavaException: exiting..."
) ;
}
(*(env))->ThrowNew(env, ije, msg) ;
}
int
check_exception_from_java(JNIEnv *env){
jthrowable exc ;
int
ret = 0 ;
exc = (*(env))->ExceptionOccurred(env) ;
if
(exc != NULL){
(*(env))->ExceptionClear(env) ;
if
((*(env))->Throw(env, exc)){
(*(env))->FatalError(env,
"Throw of InlineJava*Exception failed: exiting..."
) ;
}
ret = 1 ;
}
return
ret ;
}
jobject create_primitive_object(JNIEnv *env,
char
f,
char
*cls_name, jvalue val){
jclass arg_cls ;
jmethodID mid ;
jobject ret = NULL ;
char
sign[64] ;
arg_cls = (*(env))->FindClass(env, cls_name) ;
if
(check_exception_from_java(env)){
return
NULL ;
}
sprintf
(sign,
"(%c)V"
, f) ;
mid = (*(env))->GetMethodID(env, arg_cls,
"<init>"
, sign) ;
if
(check_exception_from_java(env)){
return
NULL ;
}
ret = (*(env))->NewObjectA(env, arg_cls, mid, &val) ;
if
(check_exception_from_java(env)){
return
NULL ;
}
return
ret ;
}
jobject extract_va_arg(JNIEnv *env,
va_list
*list,
char
f){
jobject ret = NULL ;
jvalue val ;
switch
(f){
case
'B'
:
val.b = (jbyte)
va_arg
(*list,
int
) ;
ret = create_primitive_object(env, f,
"java/lang/Byte"
, val) ;
break
;
case
'S'
:
val.s = (jshort)
va_arg
(*list,
int
) ;
ret = create_primitive_object(env, f,
"java/lang/Short"
, val) ;
break
;
case
'I'
:
val.i = (jint)
va_arg
(*list,
int
) ;
ret = create_primitive_object(env, f,
"java/lang/Integer"
, val) ;
break
;
case
'J'
:
val.d = (jdouble)
va_arg
(*list,
double
) ;
ret = create_primitive_object(env, f,
"java/lang/Long"
, val) ;
break
;
case
'F'
:
val.i = (jint)
va_arg
(*list,
int
) ;
ret = create_primitive_object(env, f,
"java/lang/Float"
, val) ;
break
;
case
'D'
:
val.d = (jdouble)
va_arg
(*list,
double
) ;
ret = create_primitive_object(env, f,
"java/lang/Double"
, val) ;
break
;
case
'Z'
:
val.z = (jboolean)
va_arg
(*list,
int
) ;
ret = create_primitive_object(env, f,
"java/lang/Boolean"
, val) ;
break
;
case
'C'
:
val.c = (jchar)
va_arg
(*list,
int
) ;
ret = create_primitive_object(env, f,
"java/lang/Character"
, val) ;
break
;
}
return
ret ;
}
jobject JNICALL generic_perl_native(JNIEnv *env, jobject obj, ...){
va_list
list ;
jclass cls ;
jmethodID mid ;
jstring jfmt ;
char
*fmt ;
int
fmt_len ;
jclass obj_cls ;
jobjectArray obj_array ;
jobject arg ;
int
i ;
jobject ret = NULL ;
cls = (*(env))->GetObjectClass(env, obj) ;
mid = (*(env))->GetMethodID(env, cls,
"LookupMethod"
,
"()Ljava/lang/String;"
) ;
if
(check_exception_from_java(env)){
return
NULL ;
}
jfmt = (*(env))->CallObjectMethod(env, obj, mid) ;
if
(check_exception_from_java(env)){
return
NULL ;
}
fmt = (
char
*)((*(env))->GetStringUTFChars(env, jfmt, NULL)) ;
fmt_len =
strlen
(fmt) ;
obj_cls = (*(env))->FindClass(env,
"java/lang/Object"
) ;
if
(check_exception_from_java(env)){
return
NULL ;
}
obj_array = (*(env))->NewObjectArray(env, fmt_len, obj_cls, NULL) ;
if
(check_exception_from_java(env)){
return
NULL ;
}
(*(env))->SetObjectArrayElement(env, obj_array, 0, obj) ;
if
(check_exception_from_java(env)){
return
NULL ;
}
va_start
(list, obj) ;
for
(i = 1 ; i < fmt_len ; i++){
if
(fmt[i] !=
'L'
){
arg = extract_va_arg(env, &list, fmt[i]) ;
if
(arg == NULL){
return
NULL ;
}
}
else
{
arg = (jobject)
va_arg
(list, jobject) ;
}
(*(env))->SetObjectArrayElement(env, obj_array, i, arg) ;
if
(check_exception_from_java(env)){
return
NULL ;
}
}
va_end
(list) ;
mid = (*(env))->GetMethodID(env, cls,
"InvokePerlMethod"
,
"([Ljava/lang/Object;)Ljava/lang/Object;"
) ;
if
(check_exception_from_java(env)){
return
NULL ;
}
ret = (*(env))->CallObjectMethod(env, obj, mid, obj_array) ;
if
(check_exception_from_java(env)){
return
NULL ;
}
return
ret ;
}
JNIEXPORT
void
JNICALL Java_org_perl_inline_java_InlineJavaPerlNatives_RegisterMethod(JNIEnv *env, jobject obj, jclass cls, jstring name, jstring signature){
JNINativeMethod nm ;
nm.name = (
char
*)((*(env))->GetStringUTFChars(env, name, NULL)) ;
nm.signature = (
char
*)((*(env))->GetStringUTFChars(env, signature, NULL)) ;
nm.fnPtr = generic_perl_native ;
(*(env))->RegisterNatives(env, cls, &nm, 1) ;
(*(env))->ReleaseStringUTFChars(env, name, nm.name) ;
(*(env))->ReleaseStringUTFChars(env, signature, nm.signature) ;
if
(check_exception_from_java(env)){
return
;
}
}