func ReflectedSignature(ctx *Environment, f interface{}) (sig types.MethodSignature, err error) { sig.Return = types.Basic(types.UnspecKind) ftype := reflect.TypeOf(f) sig.Params = make([]types.Typed, 0) if ftype.Kind() != reflect.Func { err = errors.New("ReflectedSignature: f is not a function") } if err == nil && ftype.NumIn() < 2 { err = errors.New("ReflectedSignature: f is not a callback (insufficient args)") } if err == nil && ftype.NumOut() > 1 { err = errors.New("ReflectedSignature: f is not a callback (too many returns)") } if err == nil && ftype.In(0) != reflect.TypeOf(&Environment{}) { err = errors.New("bad first-arg Type: must be *Environment") } if err == nil && ftype.In(1) != reflect.TypeOf(&Object{}) { err = errors.New("bad second-arg Type: must be *Object") } if err != nil { return } for i := 2; i < ftype.NumIn(); i++ { var k types.Typed if ftype.In(i).Kind() == reflect.Ptr { if ftype.In(i) == reflect.TypeOf(&Object{}) { k = types.Class{types.JavaLangObject} } else { itype := ftype.In(i).Elem() pobj := reflect.New(itype).Interface() k, err = TypeOf(ctx, pobj) } } else { k, err = TypeOf(ctx, reflect.New(ftype.In(i)).Interface()) } if err != nil { break } sig.Params = append(sig.Params, k) } if ftype.NumOut() == 1 { var k types.Typed k, err = reflectedType(ctx, reflect.New(ftype.Out(0)).Interface()) if err == nil { sig.Return = k } } else { sig.Return = types.Basic(types.VoidKind) } return }
func reflectedType(env *Environment, v interface{}) (k types.Typed, err error) { vtype := reflect.TypeOf(v) vkind := vtype.Kind() switch vkind { case reflect.Ptr: k, err = TypeOf(env, reflect.Indirect(reflect.ValueOf(v)).Interface()) case reflect.Bool: k = types.Basic(types.BoolKind) case reflect.Uint8, reflect.Int8: k = types.Basic(types.ByteKind) case reflect.Int16, reflect.Uint16: k = types.Basic(types.ShortKind) case reflect.Int32, reflect.Uint32: k = types.Basic(types.IntKind) case reflect.Uint64, reflect.Int64: k = types.Basic(types.LongKind) case reflect.Int, reflect.Uint: k = types.Basic(types.IntKind) case reflect.Float32: k = types.Basic(types.FloatKind) case reflect.Float64: k = types.Basic(types.DoubleKind) case reflect.Struct: k = types.Class{[]string{"golang", vkind.String()}} case reflect.String: k = types.Class{types.JavaLangString} case reflect.Slice, reflect.Array: sltype := vtype.Elem() switch sltype.Kind() { case reflect.Uint8: k = types.Array{types.Basic(types.ByteKind)} case reflect.String: k = types.Array{types.Class{types.JavaLangString}} default: err = errors.New("Unhandled slice type " + sltype.String()) } default: switch T := v.(type) { default: err = errors.New(fmt.Sprintf("Unsure how to TypeOf '%s'/%T", vkind.String(), T)) } } return }
func TestJVMTrivialClass(t *testing.T) { env := setupJVM(t) for i, test := range trivialClassTests { form, err := FormFor(env, types.Basic(types.VoidKind), test.ConstArgs...) fatalIf(t, err != nil, "[%d] Error generating formFor: %v", i, err) fatalIf(t, form == "", "Got nil form") klass, err := env.NewInstanceStr(TrivialClass, test.ConstArgs...) fatalIf(t, err != nil, "[%d] Error generating formFor: %v", i, err) kused, _, err := klass.CallString(env, false, "getConstructorUsed") fatalIf(t, err != nil, "[%d] Error getting constructor used: %v", i, err) fatalIf(t, kused != form, "[%d] Constructor called was wrong (Exp: %s, got: %s)", form, kused) } }
func (self *Environment) callVoid(z interface{}, static bool, name string, params ...interface{}) (err error) { jval, meth, args, localStack, err := self.getMethod(z, static, name, types.Basic(types.VoidKind), params...) if err != nil { return } defer blowStack(self, localStack) if static { C.envCallStaticVoidMethodA(self.env, C.valObject(jval), meth.method, args.Ptr()) } else { C.envCallVoidMethodA(self.env, C.valObject(jval), meth.method, args.Ptr()) } if self.ExceptionCheck() { err = self.ExceptionOccurred() } return }
/* returns a new *Object of type *Class, using the constructor identified by []params */ func (self *Environment) NewInstance(c *Class, params ...interface{}) (o *Object, err error) { meth, alp, localStack, err := self.getClassMethod(c, false, "<init>", types.Basic(types.VoidKind), params...) // meth, alp, err := self.getObjectMethod(newObject(self, c, C.jobject( c.class)), "<init>", BasicType(JavaVoidKind), params...) if err != nil { return } defer blowStack(self, localStack) obj := C.envNewObjectA(self.env, c.class, meth.method, alp.Ptr()) if obj != nil { obj = C.envNewGlobalRef(self.env, obj) o = newObject(obj) } else { err = self.ExceptionOccurred() } return }
func (self *Environment) ToString(strobj *Object) (str string, isNull bool, err error) { var bytesObj *Object bytesObj, err = self.CallObjectObj(strobj, false, "getBytes", types.Array{types.Basic(types.ByteKind)}, self.utf8()) if err == nil && bytesObj == nil { isNull = true return } if err == nil { defer self.DeleteLocalRef(bytesObj) alen := C.envGetArrayLength(self.env, bytesObj.object) _false := C.jboolean(C.JNI_FALSE) ptr := C.envGetByteArrayElements(self.env, bytesObj.object, &_false) defer C.envReleaseByteArrayElements(self.env, bytesObj.object, ptr, 0) str = string(C.GoBytes(unsafe.Pointer(ptr), C.int(alen))) } return }
func (self *Environment) callFloat(z interface{}, static bool, name string, params ...interface{}) (v float32, err error) { jval, meth, args, localStack, err := self.getMethod(z, static, name, types.Basic(types.FloatKind), params...) if err != nil { return } defer blowStack(self, localStack) var ji C.jfloat if static { ji = C.envCallStaticFloatMethodA(self.env, C.valObject(jval), meth.method, args.Ptr()) } else { ji = C.envCallFloatMethodA(self.env, C.valObject(jval), meth.method, args.Ptr()) } if self.ExceptionCheck() { err = self.ExceptionOccurred() } v = float32(ji) return }
func (self *Environment) callShort(z interface{}, static bool, name string, params ...interface{}) (v int16, err error) { jval, meth, args, localStack, err := self.getMethod(z, static, name, types.Basic(types.ShortKind), params...) if err != nil { return } defer blowStack(self, localStack) var oval C.jshort if static { oval = C.envCallStaticShortMethodA(self.env, C.valObject(jval), meth.method, args.Ptr()) } else { oval = C.envCallShortMethodA(self.env, C.valObject(jval), meth.method, args.Ptr()) } if self.ExceptionCheck() { err = self.ExceptionOccurred() } if err == nil { v = int16(oval) } return }
package gojvm import ( "gojvm/types" "testing" ) type formForTest struct { rtype types.Typed params []interface{} eform string eerror error } var formOfTests = []formForTest{ formForTest{types.Basic(types.VoidKind), []interface{}{}, "()V", nil}, formForTest{types.Basic(types.VoidKind), []interface{}{int(5)}, "(I)V", nil}, formForTest{types.Basic(types.VoidKind), []interface{}{int16(5)}, "(S)V", nil}, formForTest{types.Basic(types.VoidKind), []interface{}{int64(5)}, "(J)V", nil}, formForTest{types.Basic(types.VoidKind), []interface{}{"5"}, "(Ljava/lang/String;)V", nil}, formForTest{types.Basic(types.VoidKind), []interface{}{"5", &Object{}}, "(Ljava/lang/String;Ljava/lang/Object;)V", nil}, formForTest{types.Basic(types.ShortKind), []interface{}{int64(5)}, "(J)S", nil}, formForTest{types.Basic(types.BoolKind), []interface{}{int(0)}, "(I)Z", nil}, formForTest{types.Class{types.JavaLangObject}, []interface{}{int(0)}, "(I)Ljava/lang/Object;", nil}, formForTest{types.Array{types.Basic(types.ByteKind)}, []interface{}{[]byte{1, 2, 3}}, "([B)[B", nil}, } func TestTrivialFormFor(t *testing.T) { env := setupJVM(t) for i, test := range formOfTests { form, err := FormFor(env, test.rtype, test.params...)