func (g *JavaGen) genJNIConstructor(f *types.Func, sName string) { if !g.isSigSupported(f.Type()) { return } sig := f.Type().(*types.Signature) res := sig.Results() g.Printf("JNIEXPORT jobject JNICALL\n") g.Printf("Java_%s_%s_%s(JNIEnv *env, jclass clazz", g.jniPkgName(), sName, java.JNIMangle("__"+f.Name())) params := sig.Params() for i := 0; i < params.Len(); i++ { v := params.At(i) jt := g.jniType(v.Type()) g.Printf(", %s %s", jt, g.paramName(params, i)) } g.Printf(") {\n") g.Indent() for i := 0; i < params.Len(); i++ { name := g.paramName(params, i) g.genJavaToC(name, params.At(i).Type(), modeTransient) } // Constructors always return a mandatory *T and an optional error if res.Len() == 1 { g.Printf("int32_t refnum = proxy%s__%s(", g.pkgPrefix, f.Name()) } else { g.Printf("struct proxy%s__%s_return res = proxy%s__%s(", g.pkgPrefix, f.Name(), g.pkgPrefix, f.Name()) } for i := 0; i < params.Len(); i++ { if i > 0 { g.Printf(", ") } g.Printf("_%s", g.paramName(params, i)) } g.Printf(");\n") for i := 0; i < params.Len(); i++ { g.genRelease(g.paramName(params, i), params.At(i).Type(), modeTransient) } // Extract multi returns and handle errors if res.Len() == 2 { g.Printf("int32_t refnum = res.r0;\n") g.genCToJava("_err", "res.r1", res.At(1).Type(), modeRetained) g.Printf("go_seq_maybe_throw_exception(env, _err);\n") } // Pass no proxy class so that the Seq.Ref is returned instead. g.Printf("return go_seq_from_refnum(env, refnum, NULL, NULL);\n") g.Outdent() g.Printf("}\n\n") }
func (g *JavaGen) GenC() error { var pkgName, pkgPath string if g.Pkg != nil { pkgName = g.Pkg.Name() pkgPath = g.Pkg.Path() } else { pkgName = "universe" } g.Printf(cPreamble, g.gobindOpts(), pkgPath) g.Printf("#include %q\n", pkgName+".h") if g.Pkg != nil { for _, pkg := range g.Pkg.Imports() { if g.validPkg(pkg) { g.Printf("#include \"%s.h\"\n", pkg.Name()) } } } g.Printf("\n") for _, iface := range g.interfaces { g.Printf("jclass proxy_class_%s_%s;\n", g.pkgPrefix, iface.obj.Name()) g.Printf("jmethodID proxy_class_%s_%s_cons;\n", g.pkgPrefix, iface.obj.Name()) for _, m := range iface.summary.callable { if !g.isSigSupported(m.Type()) { g.Printf("// skipped method %s.%s with unsupported parameter or return types\n\n", iface.obj.Name(), m.Name()) continue } g.Printf("static jmethodID mid_%s_%s;\n", iface.obj.Name(), m.Name()) } } for _, s := range g.structs { g.Printf("jclass proxy_class_%s_%s;\n", g.pkgPrefix, s.obj.Name()) g.Printf("jmethodID proxy_class_%s_%s_cons;\n", g.pkgPrefix, s.obj.Name()) } g.Printf("\n") g.Printf("JNIEXPORT void JNICALL\n") g.Printf("Java_%s_%s__1init(JNIEnv *env, jclass _unused) {\n", g.jniPkgName(), g.className()) g.Indent() g.Printf("jclass clazz;\n") for _, s := range g.structs { if jinf, ok := g.jstructs[s.obj]; ok { // Leave the class and constructor NULL for Java classes with no // default constructor. if !jinf.genNoargCon { continue } } g.Printf("clazz = (*env)->FindClass(env, %q);\n", g.jniClassSigPrefix(s.obj.Pkg())+s.obj.Name()) g.Printf("proxy_class_%s_%s = (*env)->NewGlobalRef(env, clazz);\n", g.pkgPrefix, s.obj.Name()) g.Printf("proxy_class_%s_%s_cons = (*env)->GetMethodID(env, clazz, \"<init>\", \"(Lgo/Seq$Ref;)V\");\n", g.pkgPrefix, s.obj.Name()) } for _, iface := range g.interfaces { pkg := iface.obj.Pkg() g.Printf("clazz = (*env)->FindClass(env, %q);\n", g.jniClassSigPrefix(pkg)+JavaClassName(pkg)+"$proxy"+iface.obj.Name()) g.Printf("proxy_class_%s_%s = (*env)->NewGlobalRef(env, clazz);\n", g.pkgPrefix, iface.obj.Name()) g.Printf("proxy_class_%s_%s_cons = (*env)->GetMethodID(env, clazz, \"<init>\", \"(Lgo/Seq$Ref;)V\");\n", g.pkgPrefix, iface.obj.Name()) if isErrorType(iface.obj.Type()) { // As a special case, Java Exceptions are passed to Go pretending to implement the Go error interface. // To complete the illusion, use the Throwable.getMessage method for proxied calls to the error.Error method. g.Printf("clazz = (*env)->FindClass(env, \"java/lang/Throwable\");\n") g.Printf("mid_error_Error = (*env)->GetMethodID(env, clazz, \"getMessage\", \"()Ljava/lang/String;\");\n") continue } g.Printf("clazz = (*env)->FindClass(env, %q);\n", g.jniClassSigPrefix(pkg)+iface.obj.Name()) for _, m := range iface.summary.callable { if !g.isSigSupported(m.Type()) { g.Printf("// skipped method %s.%s with unsupported parameter or return types\n\n", iface.obj.Name(), m.Name()) continue } sig := m.Type().(*types.Signature) res := sig.Results() retSig := "V" if res.Len() > 0 { if t := res.At(0).Type(); !isErrorType(t) { retSig = g.jniSigType(t) } } var jniParams string params := sig.Params() for i := 0; i < params.Len(); i++ { jniParams += g.jniSigType(params.At(i).Type()) } g.Printf("mid_%s_%s = (*env)->GetMethodID(env, clazz, %q, \"(%s)%s\");\n", iface.obj.Name(), m.Name(), javaNameReplacer(lowerFirst(m.Name())), jniParams, retSig) } g.Printf("\n") } g.Outdent() g.Printf("}\n\n") for _, f := range g.funcs { g.genJNIFunc(f, "", nil, false, false) } for _, s := range g.structs { sName := s.obj.Name() cons := g.constructors[s.obj] jinf := g.jstructs[s.obj] for _, f := range cons { g.genJNIConstructor(f, sName) } if len(cons) == 0 && (jinf == nil || jinf.genNoargCon) { g.Printf("JNIEXPORT jobject JNICALL\n") g.Printf("Java_%s_%s_%s(JNIEnv *env, jclass clazz) {\n", g.jniPkgName(), sName, java.JNIMangle("__New")) g.Indent() g.Printf("int32_t refnum = new_%s_%s();\n", g.pkgPrefix, sName) // Pass no proxy class so that the Seq.Ref is returned instead. g.Printf("return go_seq_from_refnum(env, refnum, NULL, NULL);\n") g.Outdent() g.Printf("}\n\n") } for _, m := range exportedMethodSet(types.NewPointer(s.obj.Type())) { var jm *java.Func if jinf != nil { jm = jinf.methods[m.Name()] } g.genJNIFunc(m, sName, jm, false, jinf != nil) } for _, f := range exportedFields(s.t) { g.genJNIField(s.obj, f) } } for _, iface := range g.interfaces { for _, m := range iface.summary.callable { g.genJNIFunc(m, iface.obj.Name(), nil, true, false) g.genMethodInterfaceProxy(iface.obj.Name(), m) } } for _, v := range g.vars { g.genJNIVar(v) } if len(g.err) > 0 { return g.err } return nil }