bind: support exported variables

basic types, struct*, interface.

TODO: error, non-pointer struct, pointer basic types, slice of bytes.

Update golang/go#12475.

Change-Id: I5ff91059b1f963b0cadb6f76cb0e12f7b6b98718
Reviewed-on: https://go-review.googlesource.com/15340
Reviewed-by: David Crawshaw <crawshaw@golang.org>
diff --git a/bind/bind_test.go b/bind/bind_test.go
index eb75115..98b88c6 100644
--- a/bind/bind_test.go
+++ b/bind/bind_test.go
@@ -32,6 +32,7 @@
 	"testdata/issue12328.go",
 	"testdata/issue12403.go",
 	"testdata/try.go",
+	"testdata/vars.go",
 }
 
 var fset = token.NewFileSet()
diff --git a/bind/gengo.go b/bind/gengo.go
index 258621d..da3c574 100644
--- a/bind/gengo.go
+++ b/bind/gengo.go
@@ -192,6 +192,29 @@
 	g.Printf("}\n\n")
 }
 
+func (g *goGen) genVar(o *types.Var) {
+	// TODO(hyangah): non-struct pointer types (*int), struct type.
+
+	v := fmt.Sprintf("%s.%s", g.pkg.Name(), o.Name())
+
+	// var I int
+	//
+	// func var_setI(out, in *seq.Buffer)
+	g.Printf("func var_set%s(out, in *seq.Buffer) {\n", o.Name())
+	g.Indent()
+	g.genRead("v", "in", o.Type())
+	g.Printf("%s = v\n", v)
+	g.Outdent()
+	g.Printf("}\n")
+
+	// func var_getI(out, in *seq.Buffer)
+	g.Printf("func var_get%s(out, in *seq.Buffer) {\n", o.Name())
+	g.Indent()
+	g.genWrite(v, "out", o.Type())
+	g.Outdent()
+	g.Printf("}\n")
+}
+
 func (g *goGen) genInterface(obj *types.TypeName) {
 	iface := obj.Type().(*types.Named).Underlying().(*types.Interface)
 	ifaceDesc := fmt.Sprintf("go.%s.%s", g.pkg.Name(), obj.Name())
@@ -374,7 +397,7 @@
 func (g *goGen) gen() error {
 	g.genPreamble()
 
-	var funcs []string
+	var funcs, vars []string
 
 	scope := g.pkg.Scope()
 	names := scope.Names()
@@ -401,6 +424,9 @@
 			case *types.Interface:
 				g.genInterface(obj)
 			}
+		case *types.Var:
+			g.genVar(obj)
+			vars = append(vars, obj.Name())
 		case *types.Const:
 		default:
 			g.errorf("not yet supported, name for %v / %T", obj, obj)
@@ -418,6 +444,18 @@
 		g.Printf("}\n")
 	}
 
+	if len(vars) > 0 {
+		g.Printf("func init() {\n")
+		g.Indent()
+		for _, name := range vars {
+			varDesc := fmt.Sprintf("%s.%s", g.pkg.Name(), name)
+			g.Printf("seq.Register(%q, %d, var_set%s)\n", varDesc, 1, name)
+			g.Printf("seq.Register(%q, %d, var_get%s)\n", varDesc, 2, name)
+		}
+		g.Outdent()
+		g.Printf("}\n")
+	}
+
 	if len(g.err) > 0 {
 		return g.err
 	}
diff --git a/bind/genjava.go b/bind/genjava.go
index d4bd18e..4b14860 100644
--- a/bind/genjava.go
+++ b/bind/genjava.go
@@ -459,6 +459,35 @@
 	return nil
 }
 
+func (g *javaGen) genVar(o *types.Var) {
+	jType := g.javaType(o.Type())
+	varDesc := fmt.Sprintf("%s.%s", g.pkg.Name(), o.Name())
+
+	// setter
+	g.Printf("public static void set%s(%s v) {\n", o.Name(), jType)
+	g.Indent()
+	g.Printf("Seq in = new Seq();\n")
+	g.Printf("Seq out = new Seq();\n")
+	g.Printf("in.write%s;\n", seqWrite(o.Type(), "v"))
+	g.Printf("Seq.send(%q, 1, in, out);\n", varDesc)
+	g.Outdent()
+	g.Printf("}\n")
+	g.Printf("\n")
+
+	// getter
+	g.Printf("public static %s get%s() {\n", jType, o.Name())
+	g.Indent()
+	g.Printf("Seq in = new Seq();\n")
+	g.Printf("Seq out = new Seq();\n")
+	g.Printf("Seq.send(%q, 2, in, out);\n", varDesc)
+	g.Printf("%s ", jType)
+	g.genRead("v", "out", o.Type())
+	g.Printf("return v;\n")
+	g.Outdent()
+	g.Printf("}\n")
+	g.Printf("\n")
+}
+
 func (g *javaGen) genFunc(o *types.Func, method bool) {
 	if err := g.funcSignature(o, !method); err != nil {
 		g.errorf("%v", err)
@@ -634,9 +663,11 @@
 	g.Printf("public abstract class %s {\n", g.className())
 	g.Indent()
 	g.Printf("private %s() {} // uninstantiable\n\n", g.className())
+
+	var funcs []string
+
 	scope := g.pkg.Scope()
 	names := scope.Names()
-	var funcs []string
 	for _, name := range names {
 		obj := scope.Lookup(name)
 		if !obj.Exported() {
@@ -663,6 +694,8 @@
 			}
 		case *types.Const:
 			g.genConst(o)
+		case *types.Var:
+			g.genVar(o)
 		default:
 			g.errorf("unsupported exported type: %T", obj)
 		}
diff --git a/bind/genobjc.go b/bind/genobjc.go
index 181b17a..25bc35c 100644
--- a/bind/genobjc.go
+++ b/bind/genobjc.go
@@ -29,6 +29,7 @@
 	funcs      []*types.Func
 	names      []*types.TypeName
 	constants  []*types.Const
+	vars       []*types.Var
 }
 
 func (g *objcGen) init() {
@@ -56,9 +57,10 @@
 				continue
 			}
 			g.constants = append(g.constants, obj)
+		case *types.Var:
+			g.vars = append(g.vars, obj)
 		default:
 			g.errorf("unsupported exported type for %s: %T", obj.Name(), obj)
-			// TODO(hyangah): *types.Var
 		}
 	}
 }
@@ -119,6 +121,14 @@
 		g.Printf("\n")
 	}
 
+	// var
+	for _, obj := range g.vars {
+		objcType := g.objcType(obj.Type())
+		g.Printf("FOUNDATION_EXPORT void %s_set%s(%s v);\n", g.namePrefix, obj.Name(), objcType)
+		g.Printf("FOUNDATION_EXPORT %s %s%s();\n", objcType, g.namePrefix, obj.Name())
+		g.Printf("\n")
+	}
+
 	// static functions.
 	for _, obj := range g.funcs {
 		g.genFuncH(obj)
@@ -186,6 +196,15 @@
 	if len(g.constants) > 0 {
 		g.Printf("\n")
 	}
+
+	// vars
+	for _, o := range g.vars {
+		g.genVarM(o)
+	}
+	if len(g.vars) > 0 {
+		g.Printf("\n")
+	}
+
 	// global functions.
 	for _, obj := range g.funcs {
 		g.genFuncM(obj)
@@ -210,6 +229,35 @@
 	return nil
 }
 
+func (g *objcGen) genVarM(o *types.Var) {
+	varDesc := fmt.Sprintf("%q", g.pkg.Name()+"."+o.Name())
+	objcType := g.objcType(o.Type())
+
+	// setter
+	s1 := &funcSummary{
+		name:   g.namePrefix + "_set" + o.Name(),
+		ret:    "void",
+		params: []paramInfo{{typ: o.Type(), name: "v"}},
+	}
+	g.Printf("void %s(%s v) {\n", s1.name, objcType)
+	g.Indent()
+	g.genFunc(varDesc, "1", s1, false)
+	g.Outdent()
+	g.Printf("}\n\n")
+
+	// getter
+	s2 := &funcSummary{
+		name:      g.namePrefix + o.Name(),
+		ret:       objcType,
+		retParams: []paramInfo{{typ: o.Type(), name: "ret"}},
+	}
+	g.Printf("%s %s() {\n", s2.ret, s2.name)
+	g.Indent()
+	g.genFunc(varDesc, "2", s2, false)
+	g.Outdent()
+	g.Printf("}\n\n")
+}
+
 func (g *objcGen) genConstM(o *types.Const) {
 	cName := fmt.Sprintf("%s%s", g.namePrefix, o.Name())
 	cType := g.objcType(o.Type())
diff --git a/bind/java/SeqTest.java b/bind/java/SeqTest.java
index 2f0927f..a797543 100644
--- a/bind/java/SeqTest.java
+++ b/bind/java/SeqTest.java
@@ -33,6 +33,34 @@
     assertEquals("const MaxFloat32", 3.40282346638528859811704183484516925440e+38, Testpkg.MaxFloat32, 0.0001);
     assertEquals("const Log2E", 1/0.693147180559945309417232121458176568075500134360255254120680009, Testpkg.Log2E, 0.0001);
   }
+
+  public void testVar() {
+    assertEquals("var StringVar", "a string var", Testpkg.getStringVar());
+
+    String newStringVar = "a new string var";
+    Testpkg.setStringVar(newStringVar);
+    assertEquals("var StringVar", newStringVar, Testpkg.getStringVar());
+
+    assertEquals("var IntVar", 77, Testpkg.getIntVar());
+
+    long newIntVar = 777;
+    Testpkg.setIntVar(newIntVar);
+    assertEquals("var IntVar", newIntVar, Testpkg.getIntVar());
+
+    Testpkg.S s0 = Testpkg.getStructVar();
+    assertEquals("var StructVar", "a struct var", s0.String());
+    Testpkg.S s1 = Testpkg.New();
+    Testpkg.setStructVar(s1);
+    assertEquals("var StructVar", s1.String(), Testpkg.getStructVar().String());
+
+    // TODO(hyangah): handle nil return value (translate to null)
+
+    AnI obj = new AnI();
+    obj.name = "this is an I";
+    Testpkg.setInterfaceVar(obj);
+    assertEquals("var InterfaceVar", obj.String(), Testpkg.getInterfaceVar().String());
+  }
+
   public void testAssets() {
     String want = "Hello, Assets.\n";
     String got = Testpkg.ReadAsset();
diff --git a/bind/java/testpkg/testpkg.go b/bind/java/testpkg/testpkg.go
index 1b3f498..806e3c7 100644
--- a/bind/java/testpkg/testpkg.go
+++ b/bind/java/testpkg/testpkg.go
@@ -39,6 +39,13 @@
 	Log2E                          = math.Log2E
 )
 
+var (
+	StringVar    = "a string var"
+	IntVar       = 77
+	StructVar    = &S{name: "a struct var"}
+	InterfaceVar I
+)
+
 type I interface {
 	F()
 
@@ -104,8 +111,10 @@
 	numSCollected++
 }
 
+var seq = 0
+
 func New() *S {
-	s := &S{innerObj: new(int), name: "new"}
+	s := &S{innerObj: new(int), name: fmt.Sprintf("new%d", seq)}
 	runtime.SetFinalizer(s.innerObj, finalizeInner)
 	return s
 }
diff --git a/bind/objc/SeqTest.m b/bind/objc/SeqTest.m
index 5d1cbf8..77a1281 100644
--- a/bind/objc/SeqTest.m
+++ b/bind/objc/SeqTest.m
@@ -271,6 +271,50 @@
   }
 }
 
+void testVar() {
+  NSString *s = GoTestpkgStringVar();
+  if (![s isEqualToString:@"a string var"]) {
+    ERROR(@"GoTestpkgStringVar = %@, want 'a string var'", s);
+  }
+  s = @"a new string var";
+  GoTestpkg_setStringVar(s);
+  NSString *s2 = GoTestpkgStringVar();
+  if (![s2 isEqualToString:s]) {
+    ERROR(@"GoTestpkgStringVar = %@, want %@", s2, s);
+  }
+
+  int64_t i = GoTestpkgIntVar();
+  if (i != 77) {
+    ERROR(@"GoTestpkgIntVar = %lld, want 77", i);
+  }
+  GoTestpkg_setIntVar(777);
+  i = GoTestpkgIntVar();
+  if (i != 777) {
+    ERROR(@"GoTestpkgIntVar = %lld, want 777", i);
+  }
+
+  GoTestpkgNode *n0 = GoTestpkgStructVar();
+  if (![n0.V isEqualToString:@"a struct var"]) {
+    ERROR(@"GoTestpkgStructVar = %@, want 'a struct var'", n0.V);
+  }
+  GoTestpkgNode *n1 = GoTestpkgNewNode(@"a new struct var");
+  GoTestpkg_setStructVar(n1);
+  GoTestpkgNode *n2 = GoTestpkgStructVar();
+  if (![n2.V isEqualToString:@"a new struct var"]) {
+    ERROR(@"GoTestpkgStructVar = %@, want 'a new struct var'", n2.V);
+  }
+
+  Number *num = [[Number alloc] init];
+  num.value = 12345;
+  GoTestpkg_setInterfaceVar(num);
+  id<GoTestpkgI> iface = GoTestpkgInterfaceVar();
+  int64_t x = [iface Times:10];
+  int64_t y = [num Times:10];
+  if (x != y) {
+    ERROR(@"GoTestpkgInterfaceVar Times 10 = %lld, want %lld", x, y);
+  }
+}
+
 // Invokes functions and object methods defined in Testpkg.h.
 //
 // TODO(hyangah): apply testing framework (e.g. XCTestCase)
@@ -286,8 +330,6 @@
       ERROR(@"GoTestpkgSum(31, 21) = %lld, want 52\n", sum);
     }
 
-    testConst();
-
     testHello(@"세계"); // korean, utf-8, world.
 
     unichar t[] = {
@@ -315,7 +357,11 @@
             numI);
     }
 
+    testConst();
+
     testIssue12307();
+
+    testVar();
   }
 
   fprintf(stderr, "%s\n", err ? "FAIL" : "PASS");
diff --git a/bind/objc/testpkg/go_testpkg/go_testpkg.go b/bind/objc/testpkg/go_testpkg/go_testpkg.go
index 45a23da..d6d3dbf 100644
--- a/bind/objc/testpkg/go_testpkg/go_testpkg.go
+++ b/bind/objc/testpkg/go_testpkg/go_testpkg.go
@@ -158,6 +158,26 @@
 	testpkg.Int(param_x)
 }
 
+func var_setIntVar(out, in *seq.Buffer) {
+	v := in.ReadInt()
+	testpkg.IntVar = v
+}
+func var_getIntVar(out, in *seq.Buffer) {
+	out.WriteInt(testpkg.IntVar)
+}
+func var_setInterfaceVar(out, in *seq.Buffer) {
+	var v testpkg.I
+	v_ref := in.ReadRef()
+	if v_ref.Num < 0 { // go object
+		v = v_ref.Get().(testpkg.I)
+	} else { // foreign object
+		v = (*proxyI)(v_ref)
+	}
+	testpkg.InterfaceVar = v
+}
+func var_getInterfaceVar(out, in *seq.Buffer) {
+	out.WriteGoRef(testpkg.InterfaceVar)
+}
 func proxy_Multiply(out, in *seq.Buffer) {
 	param_idx := in.ReadInt32()
 	param_val := in.ReadInt32()
@@ -312,6 +332,22 @@
 	seq.Register(proxyS_Descriptor, proxyS_TryTwoStrings_Code, proxyS_TryTwoStrings)
 }
 
+func var_setStringVar(out, in *seq.Buffer) {
+	v := in.ReadString()
+	testpkg.StringVar = v
+}
+func var_getStringVar(out, in *seq.Buffer) {
+	out.WriteString(testpkg.StringVar)
+}
+func var_setStructVar(out, in *seq.Buffer) {
+	// Must be a Go object
+	v_ref := in.ReadRef()
+	v := v_ref.Get().(*testpkg.Node)
+	testpkg.StructVar = v
+}
+func var_getStructVar(out, in *seq.Buffer) {
+	out.WriteGoRef(testpkg.StructVar)
+}
 func proxy_Sum(out, in *seq.Buffer) {
 	param_x := in.ReadInt64()
 	param_y := in.ReadInt64()
@@ -343,3 +379,13 @@
 	seq.Register("testpkg", 16, proxy_Sum)
 	seq.Register("testpkg", 17, proxy_UnregisterI)
 }
+func init() {
+	seq.Register("testpkg.IntVar", 1, var_setIntVar)
+	seq.Register("testpkg.IntVar", 2, var_getIntVar)
+	seq.Register("testpkg.InterfaceVar", 1, var_setInterfaceVar)
+	seq.Register("testpkg.InterfaceVar", 2, var_getInterfaceVar)
+	seq.Register("testpkg.StringVar", 1, var_setStringVar)
+	seq.Register("testpkg.StringVar", 2, var_getStringVar)
+	seq.Register("testpkg.StructVar", 1, var_setStructVar)
+	seq.Register("testpkg.StructVar", 2, var_getStructVar)
+}
diff --git a/bind/objc/testpkg/objc_testpkg/GoTestpkg.h b/bind/objc/testpkg/objc_testpkg/GoTestpkg.h
index 8c33bc7..5f4a469 100644
--- a/bind/objc/testpkg/objc_testpkg/GoTestpkg.h
+++ b/bind/objc/testpkg/objc_testpkg/GoTestpkg.h
@@ -56,6 +56,18 @@
 FOUNDATION_EXPORT const float GoTestpkgSmallestNonzeroFloat32;
 FOUNDATION_EXPORT const double GoTestpkgSmallestNonzeroFloat64;
 
+FOUNDATION_EXPORT void GoTestpkg_setIntVar(int v);
+FOUNDATION_EXPORT int GoTestpkgIntVar();
+
+FOUNDATION_EXPORT void GoTestpkg_setInterfaceVar(id<GoTestpkgI> v);
+FOUNDATION_EXPORT id<GoTestpkgI> GoTestpkgInterfaceVar();
+
+FOUNDATION_EXPORT void GoTestpkg_setStringVar(NSString* v);
+FOUNDATION_EXPORT NSString* GoTestpkgStringVar();
+
+FOUNDATION_EXPORT void GoTestpkg_setStructVar(GoTestpkgNode* v);
+FOUNDATION_EXPORT GoTestpkgNode* GoTestpkgStructVar();
+
 FOUNDATION_EXPORT NSData* GoTestpkgBytesAppend(NSData* a, NSData* b);
 
 FOUNDATION_EXPORT BOOL GoTestpkgCallIError(id<GoTestpkgI> i, BOOL triggerError, NSError** error);
diff --git a/bind/objc/testpkg/objc_testpkg/GoTestpkg.m b/bind/objc/testpkg/objc_testpkg/GoTestpkg.m
index 4ef2d3c..72b96db 100644
--- a/bind/objc/testpkg/objc_testpkg/GoTestpkg.m
+++ b/bind/objc/testpkg/objc_testpkg/GoTestpkg.m
@@ -312,6 +312,101 @@
 const float GoTestpkgSmallestNonzeroFloat32 = 0;
 const double GoTestpkgSmallestNonzeroFloat64 = 5e-324;
 
+void GoTestpkg_setIntVar(int v) {
+	GoSeq in_ = {};
+	GoSeq out_ = {};
+	go_seq_writeInt(&in_, v);
+	go_seq_send("testpkg.IntVar", 1, &in_, &out_);
+	go_seq_free(&in_);
+	go_seq_free(&out_);
+}
+
+int GoTestpkgIntVar() {
+	GoSeq in_ = {};
+	GoSeq out_ = {};
+	go_seq_send("testpkg.IntVar", 2, &in_, &out_);
+	int ret = go_seq_readInt(&out_);
+	go_seq_free(&in_);
+	go_seq_free(&out_);
+	return ret;
+}
+
+void GoTestpkg_setInterfaceVar(id<GoTestpkgI> v) {
+	GoSeq in_ = {};
+	GoSeq out_ = {};
+	if ([(id<NSObject>)(v) isKindOfClass:[GoTestpkgI class]]) {
+		id<goSeqRefInterface> v_proxy = (id<goSeqRefInterface>)(v);
+		go_seq_writeRef(&in_, v_proxy.ref);
+	} else {
+		go_seq_writeObjcRef(&in_, v);
+	}
+	go_seq_send("testpkg.InterfaceVar", 1, &in_, &out_);
+	go_seq_free(&in_);
+	go_seq_free(&out_);
+}
+
+id<GoTestpkgI> GoTestpkgInterfaceVar() {
+	GoSeq in_ = {};
+	GoSeq out_ = {};
+	go_seq_send("testpkg.InterfaceVar", 2, &in_, &out_);
+	GoSeqRef* ret_ref = go_seq_readRef(&out_);
+	id<GoTestpkgI> ret = ret_ref.obj;
+	if (ret == NULL) {
+		ret = [[GoTestpkgI alloc] initWithRef:ret_ref];
+	}
+	go_seq_free(&in_);
+	go_seq_free(&out_);
+	return ret;
+}
+
+void GoTestpkg_setStringVar(NSString* v) {
+	GoSeq in_ = {};
+	GoSeq out_ = {};
+	go_seq_writeUTF8(&in_, v);
+	go_seq_send("testpkg.StringVar", 1, &in_, &out_);
+	go_seq_free(&in_);
+	go_seq_free(&out_);
+}
+
+NSString* GoTestpkgStringVar() {
+	GoSeq in_ = {};
+	GoSeq out_ = {};
+	go_seq_send("testpkg.StringVar", 2, &in_, &out_);
+	NSString* ret = go_seq_readUTF8(&out_);
+	go_seq_free(&in_);
+	go_seq_free(&out_);
+	return ret;
+}
+
+void GoTestpkg_setStructVar(GoTestpkgNode* v) {
+	GoSeq in_ = {};
+	GoSeq out_ = {};
+	if ([(id<NSObject>)(v) isKindOfClass:[GoTestpkgNode class]]) {
+		id<goSeqRefInterface> v_proxy = (id<goSeqRefInterface>)(v);
+		go_seq_writeRef(&in_, v_proxy.ref);
+	} else {
+		go_seq_writeObjcRef(&in_, v);
+	}
+	go_seq_send("testpkg.StructVar", 1, &in_, &out_);
+	go_seq_free(&in_);
+	go_seq_free(&out_);
+}
+
+GoTestpkgNode* GoTestpkgStructVar() {
+	GoSeq in_ = {};
+	GoSeq out_ = {};
+	go_seq_send("testpkg.StructVar", 2, &in_, &out_);
+	GoSeqRef* ret_ref = go_seq_readRef(&out_);
+	GoTestpkgNode* ret = ret_ref.obj;
+	if (ret == NULL) {
+		ret = [[GoTestpkgNode alloc] initWithRef:ret_ref];
+	}
+	go_seq_free(&in_);
+	go_seq_free(&out_);
+	return ret;
+}
+
+
 NSData* GoTestpkgBytesAppend(NSData* a, NSData* b) {
 	GoSeq in_ = {};
 	GoSeq out_ = {};
diff --git a/bind/objc/testpkg/testpkg.go b/bind/objc/testpkg/testpkg.go
index fb6150c..2a152c8 100644
--- a/bind/objc/testpkg/testpkg.go
+++ b/bind/objc/testpkg/testpkg.go
@@ -32,6 +32,13 @@
 	Log2E                          = math.Log2E
 )
 
+var (
+	StringVar    = "a string var"
+	IntVar       = 77
+	StructVar    = &Node{V: "a struct var"}
+	InterfaceVar I
+)
+
 type I interface {
 	Times(v int32) int64
 	Error(triggerError bool) error
diff --git a/bind/testdata/vars.go b/bind/testdata/vars.go
new file mode 100644
index 0000000..a863970
--- /dev/null
+++ b/bind/testdata/vars.go
@@ -0,0 +1,24 @@
+package vars
+
+var (
+	AString = "String"
+
+	AnInt         = -1
+	AnInt8  int8  = 8
+	AnInt16 int16 = 16
+	AnInt32 int32 = 32
+	AnInt64 int64 = 64
+
+	AFloat           = -2.0
+	AFloat32 float32 = 32.0
+	AFloat64 float64 = 64.0
+
+	ABool = true
+
+	AStructPtr  *S
+	AnInterface I
+)
+
+type S struct{}
+
+type I interface{}
diff --git a/bind/testdata/vars.go.golden b/bind/testdata/vars.go.golden
new file mode 100644
index 0000000..5a9d02d
--- /dev/null
+++ b/bind/testdata/vars.go.golden
@@ -0,0 +1,145 @@
+// Package go_vars is an autogenerated binder stub for package vars.
+//   gobind -lang=go vars
+//
+// File is generated by gobind. Do not edit.
+package go_vars
+
+import (
+	"golang.org/x/mobile/bind/seq"
+	"vars"
+)
+
+func var_setABool(out, in *seq.Buffer) {
+	v := in.ReadBool()
+	vars.ABool = v
+}
+func var_getABool(out, in *seq.Buffer) {
+	out.WriteBool(vars.ABool)
+}
+func var_setAFloat(out, in *seq.Buffer) {
+	v := in.ReadFloat64()
+	vars.AFloat = v
+}
+func var_getAFloat(out, in *seq.Buffer) {
+	out.WriteFloat64(vars.AFloat)
+}
+func var_setAFloat32(out, in *seq.Buffer) {
+	v := in.ReadFloat32()
+	vars.AFloat32 = v
+}
+func var_getAFloat32(out, in *seq.Buffer) {
+	out.WriteFloat32(vars.AFloat32)
+}
+func var_setAFloat64(out, in *seq.Buffer) {
+	v := in.ReadFloat64()
+	vars.AFloat64 = v
+}
+func var_getAFloat64(out, in *seq.Buffer) {
+	out.WriteFloat64(vars.AFloat64)
+}
+func var_setAString(out, in *seq.Buffer) {
+	v := in.ReadString()
+	vars.AString = v
+}
+func var_getAString(out, in *seq.Buffer) {
+	out.WriteString(vars.AString)
+}
+func var_setAStructPtr(out, in *seq.Buffer) {
+	// Must be a Go object
+	v_ref := in.ReadRef()
+	v := v_ref.Get().(*vars.S)
+	vars.AStructPtr = v
+}
+func var_getAStructPtr(out, in *seq.Buffer) {
+	out.WriteGoRef(vars.AStructPtr)
+}
+func var_setAnInt(out, in *seq.Buffer) {
+	v := in.ReadInt()
+	vars.AnInt = v
+}
+func var_getAnInt(out, in *seq.Buffer) {
+	out.WriteInt(vars.AnInt)
+}
+func var_setAnInt16(out, in *seq.Buffer) {
+	v := in.ReadInt16()
+	vars.AnInt16 = v
+}
+func var_getAnInt16(out, in *seq.Buffer) {
+	out.WriteInt16(vars.AnInt16)
+}
+func var_setAnInt32(out, in *seq.Buffer) {
+	v := in.ReadInt32()
+	vars.AnInt32 = v
+}
+func var_getAnInt32(out, in *seq.Buffer) {
+	out.WriteInt32(vars.AnInt32)
+}
+func var_setAnInt64(out, in *seq.Buffer) {
+	v := in.ReadInt64()
+	vars.AnInt64 = v
+}
+func var_getAnInt64(out, in *seq.Buffer) {
+	out.WriteInt64(vars.AnInt64)
+}
+func var_setAnInt8(out, in *seq.Buffer) {
+	v := in.ReadInt8()
+	vars.AnInt8 = v
+}
+func var_getAnInt8(out, in *seq.Buffer) {
+	out.WriteInt8(vars.AnInt8)
+}
+func var_setAnInterface(out, in *seq.Buffer) {
+	var v vars.I
+	v_ref := in.ReadRef()
+	if v_ref.Num < 0 { // go object
+		v = v_ref.Get().(vars.I)
+	} else { // foreign object
+		v = (*proxyI)(v_ref)
+	}
+	vars.AnInterface = v
+}
+func var_getAnInterface(out, in *seq.Buffer) {
+	out.WriteGoRef(vars.AnInterface)
+}
+
+const (
+	proxyI_Descriptor = "go.vars.I"
+)
+
+type proxyI seq.Ref
+
+const (
+	proxyS_Descriptor = "go.vars.S"
+)
+
+type proxyS seq.Ref
+
+func init() {
+}
+
+func init() {
+	seq.Register("vars.ABool", 1, var_setABool)
+	seq.Register("vars.ABool", 2, var_getABool)
+	seq.Register("vars.AFloat", 1, var_setAFloat)
+	seq.Register("vars.AFloat", 2, var_getAFloat)
+	seq.Register("vars.AFloat32", 1, var_setAFloat32)
+	seq.Register("vars.AFloat32", 2, var_getAFloat32)
+	seq.Register("vars.AFloat64", 1, var_setAFloat64)
+	seq.Register("vars.AFloat64", 2, var_getAFloat64)
+	seq.Register("vars.AString", 1, var_setAString)
+	seq.Register("vars.AString", 2, var_getAString)
+	seq.Register("vars.AStructPtr", 1, var_setAStructPtr)
+	seq.Register("vars.AStructPtr", 2, var_getAStructPtr)
+	seq.Register("vars.AnInt", 1, var_setAnInt)
+	seq.Register("vars.AnInt", 2, var_getAnInt)
+	seq.Register("vars.AnInt16", 1, var_setAnInt16)
+	seq.Register("vars.AnInt16", 2, var_getAnInt16)
+	seq.Register("vars.AnInt32", 1, var_setAnInt32)
+	seq.Register("vars.AnInt32", 2, var_getAnInt32)
+	seq.Register("vars.AnInt64", 1, var_setAnInt64)
+	seq.Register("vars.AnInt64", 2, var_getAnInt64)
+	seq.Register("vars.AnInt8", 1, var_setAnInt8)
+	seq.Register("vars.AnInt8", 2, var_getAnInt8)
+	seq.Register("vars.AnInterface", 1, var_setAnInterface)
+	seq.Register("vars.AnInterface", 2, var_getAnInterface)
+}
diff --git a/bind/testdata/vars.java.golden b/bind/testdata/vars.java.golden
new file mode 100644
index 0000000..bbd2c0b
--- /dev/null
+++ b/bind/testdata/vars.java.golden
@@ -0,0 +1,261 @@
+// Java class go.vars.Vars is a proxy for talking to a Go program.
+//   gobind -lang=java vars
+//
+// File is generated by gobind. Do not edit.
+package go.vars;
+
+import go.Seq;
+
+public abstract class Vars {
+    private Vars() {} // uninstantiable
+    
+    public static void setABool(boolean v) {
+        Seq in = new Seq();
+        Seq out = new Seq();
+        in.writeBool(v);
+        Seq.send("vars.ABool", 1, in, out);
+    }
+    
+    public static boolean getABool() {
+        Seq in = new Seq();
+        Seq out = new Seq();
+        Seq.send("vars.ABool", 2, in, out);
+        boolean v = out.readBool();
+        return v;
+    }
+    
+    public static void setAFloat(double v) {
+        Seq in = new Seq();
+        Seq out = new Seq();
+        in.writeFloat64(v);
+        Seq.send("vars.AFloat", 1, in, out);
+    }
+    
+    public static double getAFloat() {
+        Seq in = new Seq();
+        Seq out = new Seq();
+        Seq.send("vars.AFloat", 2, in, out);
+        double v = out.readFloat64();
+        return v;
+    }
+    
+    public static void setAFloat32(float v) {
+        Seq in = new Seq();
+        Seq out = new Seq();
+        in.writeFloat32(v);
+        Seq.send("vars.AFloat32", 1, in, out);
+    }
+    
+    public static float getAFloat32() {
+        Seq in = new Seq();
+        Seq out = new Seq();
+        Seq.send("vars.AFloat32", 2, in, out);
+        float v = out.readFloat32();
+        return v;
+    }
+    
+    public static void setAFloat64(double v) {
+        Seq in = new Seq();
+        Seq out = new Seq();
+        in.writeFloat64(v);
+        Seq.send("vars.AFloat64", 1, in, out);
+    }
+    
+    public static double getAFloat64() {
+        Seq in = new Seq();
+        Seq out = new Seq();
+        Seq.send("vars.AFloat64", 2, in, out);
+        double v = out.readFloat64();
+        return v;
+    }
+    
+    public static void setAString(String v) {
+        Seq in = new Seq();
+        Seq out = new Seq();
+        in.writeString(v);
+        Seq.send("vars.AString", 1, in, out);
+    }
+    
+    public static String getAString() {
+        Seq in = new Seq();
+        Seq out = new Seq();
+        Seq.send("vars.AString", 2, in, out);
+        String v = out.readString();
+        return v;
+    }
+    
+    public static void setAStructPtr(S v) {
+        Seq in = new Seq();
+        Seq out = new Seq();
+        in.writeRef(v.ref());
+        Seq.send("vars.AStructPtr", 1, in, out);
+    }
+    
+    public static S getAStructPtr() {
+        Seq in = new Seq();
+        Seq out = new Seq();
+        Seq.send("vars.AStructPtr", 2, in, out);
+        S v = new S(out.readRef());
+        return v;
+    }
+    
+    public static void setAnInt(long v) {
+        Seq in = new Seq();
+        Seq out = new Seq();
+        in.writeInt(v);
+        Seq.send("vars.AnInt", 1, in, out);
+    }
+    
+    public static long getAnInt() {
+        Seq in = new Seq();
+        Seq out = new Seq();
+        Seq.send("vars.AnInt", 2, in, out);
+        long v = out.readInt();
+        return v;
+    }
+    
+    public static void setAnInt16(short v) {
+        Seq in = new Seq();
+        Seq out = new Seq();
+        in.writeInt16(v);
+        Seq.send("vars.AnInt16", 1, in, out);
+    }
+    
+    public static short getAnInt16() {
+        Seq in = new Seq();
+        Seq out = new Seq();
+        Seq.send("vars.AnInt16", 2, in, out);
+        short v = out.readInt16();
+        return v;
+    }
+    
+    public static void setAnInt32(int v) {
+        Seq in = new Seq();
+        Seq out = new Seq();
+        in.writeInt32(v);
+        Seq.send("vars.AnInt32", 1, in, out);
+    }
+    
+    public static int getAnInt32() {
+        Seq in = new Seq();
+        Seq out = new Seq();
+        Seq.send("vars.AnInt32", 2, in, out);
+        int v = out.readInt32();
+        return v;
+    }
+    
+    public static void setAnInt64(long v) {
+        Seq in = new Seq();
+        Seq out = new Seq();
+        in.writeInt64(v);
+        Seq.send("vars.AnInt64", 1, in, out);
+    }
+    
+    public static long getAnInt64() {
+        Seq in = new Seq();
+        Seq out = new Seq();
+        Seq.send("vars.AnInt64", 2, in, out);
+        long v = out.readInt64();
+        return v;
+    }
+    
+    public static void setAnInt8(byte v) {
+        Seq in = new Seq();
+        Seq out = new Seq();
+        in.writeInt8(v);
+        Seq.send("vars.AnInt8", 1, in, out);
+    }
+    
+    public static byte getAnInt8() {
+        Seq in = new Seq();
+        Seq out = new Seq();
+        Seq.send("vars.AnInt8", 2, in, out);
+        byte v = out.readInt8();
+        return v;
+    }
+    
+    public static void setAnInterface(I v) {
+        Seq in = new Seq();
+        Seq out = new Seq();
+        in.writeRef(v.ref());
+        Seq.send("vars.AnInterface", 1, in, out);
+    }
+    
+    public static I getAnInterface() {
+        Seq in = new Seq();
+        Seq out = new Seq();
+        Seq.send("vars.AnInterface", 2, in, out);
+        I v = new I.Proxy(out.readRef());
+        return v;
+    }
+    
+    public interface I extends go.Seq.Object {
+        public static abstract class Stub implements I {
+            static final String DESCRIPTOR = "go.vars.I";
+            
+            private final go.Seq.Ref ref;
+            public Stub() {
+                ref = go.Seq.createRef(this);
+            }
+            
+            public go.Seq.Ref ref() { return ref; }
+            
+            public void call(int code, go.Seq in, go.Seq out) {
+                switch (code) {
+                default:
+                    throw new RuntimeException("unknown code: "+ code);
+                }
+            }
+        }
+        
+        static final class Proxy implements I {
+            static final String DESCRIPTOR = Stub.DESCRIPTOR;
+        
+            private go.Seq.Ref ref;
+        
+            Proxy(go.Seq.Ref ref) { this.ref = ref; }
+        
+            public go.Seq.Ref ref() { return ref; }
+        
+            public void call(int code, go.Seq in, go.Seq out) {
+                throw new RuntimeException("cycle: cannot call proxy");
+            }
+        
+        }
+    }
+    
+    public static final class S implements go.Seq.Object {
+        private static final String DESCRIPTOR = "go.vars.S";
+        
+        private go.Seq.Ref ref;
+        
+        private S(go.Seq.Ref ref) { this.ref = ref; }
+        
+        public go.Seq.Ref ref() { return ref; }
+        
+        public void call(int code, go.Seq in, go.Seq out) {
+            throw new RuntimeException("internal error: cycle: cannot call concrete proxy");
+        }
+        
+        @Override public boolean equals(Object o) {
+            if (o == null || !(o instanceof S)) {
+                return false;
+            }
+            S that = (S)o;
+            return true;
+        }
+        
+        @Override public int hashCode() {
+            return java.util.Arrays.hashCode(new Object[] {});
+        }
+        
+        @Override public String toString() {
+            StringBuilder b = new StringBuilder();
+            b.append("S").append("{");
+            return b.append("}").toString();
+        }
+        
+    }
+    
+    private static final String DESCRIPTOR = "vars";
+}
diff --git a/bind/testdata/vars.objc.h.golden b/bind/testdata/vars.objc.h.golden
new file mode 100644
index 0000000..7984017
--- /dev/null
+++ b/bind/testdata/vars.objc.h.golden
@@ -0,0 +1,59 @@
+// Objective-C API for talking to vars Go package.
+//   gobind -lang=objc vars
+//
+// File is generated by gobind. Do not edit.
+
+#ifndef __GoVars_H__
+#define __GoVars_H__
+
+#include <Foundation/Foundation.h>
+
+@class GoVarsS;
+
+@protocol GoVarsI
+@end
+
+@interface GoVarsS : NSObject {
+}
+@property(strong, readonly) id ref;
+
+- (id)initWithRef:(id)ref;
+@end
+
+FOUNDATION_EXPORT void GoVars_setABool(BOOL v);
+FOUNDATION_EXPORT BOOL GoVarsABool();
+
+FOUNDATION_EXPORT void GoVars_setAFloat(double v);
+FOUNDATION_EXPORT double GoVarsAFloat();
+
+FOUNDATION_EXPORT void GoVars_setAFloat32(float v);
+FOUNDATION_EXPORT float GoVarsAFloat32();
+
+FOUNDATION_EXPORT void GoVars_setAFloat64(double v);
+FOUNDATION_EXPORT double GoVarsAFloat64();
+
+FOUNDATION_EXPORT void GoVars_setAString(NSString* v);
+FOUNDATION_EXPORT NSString* GoVarsAString();
+
+FOUNDATION_EXPORT void GoVars_setAStructPtr(GoVarsS* v);
+FOUNDATION_EXPORT GoVarsS* GoVarsAStructPtr();
+
+FOUNDATION_EXPORT void GoVars_setAnInt(int v);
+FOUNDATION_EXPORT int GoVarsAnInt();
+
+FOUNDATION_EXPORT void GoVars_setAnInt16(int16_t v);
+FOUNDATION_EXPORT int16_t GoVarsAnInt16();
+
+FOUNDATION_EXPORT void GoVars_setAnInt32(int32_t v);
+FOUNDATION_EXPORT int32_t GoVarsAnInt32();
+
+FOUNDATION_EXPORT void GoVars_setAnInt64(int64_t v);
+FOUNDATION_EXPORT int64_t GoVarsAnInt64();
+
+FOUNDATION_EXPORT void GoVars_setAnInt8(int8_t v);
+FOUNDATION_EXPORT int8_t GoVarsAnInt8();
+
+FOUNDATION_EXPORT void GoVars_setAnInterface(id<GoVarsI> v);
+FOUNDATION_EXPORT id<GoVarsI> GoVarsAnInterface();
+
+#endif
diff --git a/bind/testdata/vars.objc.m.golden b/bind/testdata/vars.objc.m.golden
new file mode 100644
index 0000000..3bb1288
--- /dev/null
+++ b/bind/testdata/vars.objc.m.golden
@@ -0,0 +1,308 @@
+// Objective-C API for talking to vars Go package.
+//   gobind -lang=objc vars
+//
+// File is generated by gobind. Do not edit.
+
+#include "GoVars.h"
+#include <Foundation/Foundation.h>
+#include "seq.h"
+
+static NSString* errDomain = @"go.vars";
+
+@protocol goSeqRefInterface
+-(GoSeqRef*) ref;
+@end
+
+#define _DESCRIPTOR_ "vars"
+
+
+#define _GO_vars_I_DESCRIPTOR_ "go.vars.I"
+
+@interface GoVarsI : NSObject <GoVarsI> {
+}
+@property(strong, readonly) id ref;
+
+- (id)initWithRef:(id)ref;
+@end
+
+@implementation GoVarsI {
+}
+
+- (id)initWithRef:(id)ref {
+	self = [super init];
+	if (self) { _ref = ref; }
+	return self;
+}
+
+@end
+
+static void proxyGoVarsI(id obj, int code, GoSeq* in, GoSeq* out) {
+	switch (code) {
+	default:
+		NSLog(@"unknown code %x for _GO_vars_I_DESCRIPTOR_", code);
+	}
+}
+
+#define _GO_vars_S_DESCRIPTOR_ "go.vars.S"
+
+@implementation GoVarsS {
+}
+
+- (id)initWithRef:(id)ref {
+	self = [super init];
+	if (self) { _ref = ref; }
+	return self;
+}
+
+@end
+
+void GoVars_setABool(BOOL v) {
+	GoSeq in_ = {};
+	GoSeq out_ = {};
+	go_seq_writeBool(&in_, v);
+	go_seq_send("vars.ABool", 1, &in_, &out_);
+	go_seq_free(&in_);
+	go_seq_free(&out_);
+}
+
+BOOL GoVarsABool() {
+	GoSeq in_ = {};
+	GoSeq out_ = {};
+	go_seq_send("vars.ABool", 2, &in_, &out_);
+	BOOL ret = go_seq_readBool(&out_);
+	go_seq_free(&in_);
+	go_seq_free(&out_);
+	return ret;
+}
+
+void GoVars_setAFloat(double v) {
+	GoSeq in_ = {};
+	GoSeq out_ = {};
+	go_seq_writeFloat64(&in_, v);
+	go_seq_send("vars.AFloat", 1, &in_, &out_);
+	go_seq_free(&in_);
+	go_seq_free(&out_);
+}
+
+double GoVarsAFloat() {
+	GoSeq in_ = {};
+	GoSeq out_ = {};
+	go_seq_send("vars.AFloat", 2, &in_, &out_);
+	double ret = go_seq_readFloat64(&out_);
+	go_seq_free(&in_);
+	go_seq_free(&out_);
+	return ret;
+}
+
+void GoVars_setAFloat32(float v) {
+	GoSeq in_ = {};
+	GoSeq out_ = {};
+	go_seq_writeFloat32(&in_, v);
+	go_seq_send("vars.AFloat32", 1, &in_, &out_);
+	go_seq_free(&in_);
+	go_seq_free(&out_);
+}
+
+float GoVarsAFloat32() {
+	GoSeq in_ = {};
+	GoSeq out_ = {};
+	go_seq_send("vars.AFloat32", 2, &in_, &out_);
+	float ret = go_seq_readFloat32(&out_);
+	go_seq_free(&in_);
+	go_seq_free(&out_);
+	return ret;
+}
+
+void GoVars_setAFloat64(double v) {
+	GoSeq in_ = {};
+	GoSeq out_ = {};
+	go_seq_writeFloat64(&in_, v);
+	go_seq_send("vars.AFloat64", 1, &in_, &out_);
+	go_seq_free(&in_);
+	go_seq_free(&out_);
+}
+
+double GoVarsAFloat64() {
+	GoSeq in_ = {};
+	GoSeq out_ = {};
+	go_seq_send("vars.AFloat64", 2, &in_, &out_);
+	double ret = go_seq_readFloat64(&out_);
+	go_seq_free(&in_);
+	go_seq_free(&out_);
+	return ret;
+}
+
+void GoVars_setAString(NSString* v) {
+	GoSeq in_ = {};
+	GoSeq out_ = {};
+	go_seq_writeUTF8(&in_, v);
+	go_seq_send("vars.AString", 1, &in_, &out_);
+	go_seq_free(&in_);
+	go_seq_free(&out_);
+}
+
+NSString* GoVarsAString() {
+	GoSeq in_ = {};
+	GoSeq out_ = {};
+	go_seq_send("vars.AString", 2, &in_, &out_);
+	NSString* ret = go_seq_readUTF8(&out_);
+	go_seq_free(&in_);
+	go_seq_free(&out_);
+	return ret;
+}
+
+void GoVars_setAStructPtr(GoVarsS* v) {
+	GoSeq in_ = {};
+	GoSeq out_ = {};
+	if ([(id<NSObject>)(v) isKindOfClass:[GoVarsS class]]) {
+		id<goSeqRefInterface> v_proxy = (id<goSeqRefInterface>)(v);
+		go_seq_writeRef(&in_, v_proxy.ref);
+	} else {
+		go_seq_writeObjcRef(&in_, v);
+	}
+	go_seq_send("vars.AStructPtr", 1, &in_, &out_);
+	go_seq_free(&in_);
+	go_seq_free(&out_);
+}
+
+GoVarsS* GoVarsAStructPtr() {
+	GoSeq in_ = {};
+	GoSeq out_ = {};
+	go_seq_send("vars.AStructPtr", 2, &in_, &out_);
+	GoSeqRef* ret_ref = go_seq_readRef(&out_);
+	GoVarsS* ret = ret_ref.obj;
+	if (ret == NULL) {
+		ret = [[GoVarsS alloc] initWithRef:ret_ref];
+	}
+	go_seq_free(&in_);
+	go_seq_free(&out_);
+	return ret;
+}
+
+void GoVars_setAnInt(int v) {
+	GoSeq in_ = {};
+	GoSeq out_ = {};
+	go_seq_writeInt(&in_, v);
+	go_seq_send("vars.AnInt", 1, &in_, &out_);
+	go_seq_free(&in_);
+	go_seq_free(&out_);
+}
+
+int GoVarsAnInt() {
+	GoSeq in_ = {};
+	GoSeq out_ = {};
+	go_seq_send("vars.AnInt", 2, &in_, &out_);
+	int ret = go_seq_readInt(&out_);
+	go_seq_free(&in_);
+	go_seq_free(&out_);
+	return ret;
+}
+
+void GoVars_setAnInt16(int16_t v) {
+	GoSeq in_ = {};
+	GoSeq out_ = {};
+	go_seq_writeInt16(&in_, v);
+	go_seq_send("vars.AnInt16", 1, &in_, &out_);
+	go_seq_free(&in_);
+	go_seq_free(&out_);
+}
+
+int16_t GoVarsAnInt16() {
+	GoSeq in_ = {};
+	GoSeq out_ = {};
+	go_seq_send("vars.AnInt16", 2, &in_, &out_);
+	int16_t ret = go_seq_readInt16(&out_);
+	go_seq_free(&in_);
+	go_seq_free(&out_);
+	return ret;
+}
+
+void GoVars_setAnInt32(int32_t v) {
+	GoSeq in_ = {};
+	GoSeq out_ = {};
+	go_seq_writeInt32(&in_, v);
+	go_seq_send("vars.AnInt32", 1, &in_, &out_);
+	go_seq_free(&in_);
+	go_seq_free(&out_);
+}
+
+int32_t GoVarsAnInt32() {
+	GoSeq in_ = {};
+	GoSeq out_ = {};
+	go_seq_send("vars.AnInt32", 2, &in_, &out_);
+	int32_t ret = go_seq_readInt32(&out_);
+	go_seq_free(&in_);
+	go_seq_free(&out_);
+	return ret;
+}
+
+void GoVars_setAnInt64(int64_t v) {
+	GoSeq in_ = {};
+	GoSeq out_ = {};
+	go_seq_writeInt64(&in_, v);
+	go_seq_send("vars.AnInt64", 1, &in_, &out_);
+	go_seq_free(&in_);
+	go_seq_free(&out_);
+}
+
+int64_t GoVarsAnInt64() {
+	GoSeq in_ = {};
+	GoSeq out_ = {};
+	go_seq_send("vars.AnInt64", 2, &in_, &out_);
+	int64_t ret = go_seq_readInt64(&out_);
+	go_seq_free(&in_);
+	go_seq_free(&out_);
+	return ret;
+}
+
+void GoVars_setAnInt8(int8_t v) {
+	GoSeq in_ = {};
+	GoSeq out_ = {};
+	go_seq_writeInt8(&in_, v);
+	go_seq_send("vars.AnInt8", 1, &in_, &out_);
+	go_seq_free(&in_);
+	go_seq_free(&out_);
+}
+
+int8_t GoVarsAnInt8() {
+	GoSeq in_ = {};
+	GoSeq out_ = {};
+	go_seq_send("vars.AnInt8", 2, &in_, &out_);
+	int8_t ret = go_seq_readInt8(&out_);
+	go_seq_free(&in_);
+	go_seq_free(&out_);
+	return ret;
+}
+
+void GoVars_setAnInterface(id<GoVarsI> v) {
+	GoSeq in_ = {};
+	GoSeq out_ = {};
+	if ([(id<NSObject>)(v) isKindOfClass:[GoVarsI class]]) {
+		id<goSeqRefInterface> v_proxy = (id<goSeqRefInterface>)(v);
+		go_seq_writeRef(&in_, v_proxy.ref);
+	} else {
+		go_seq_writeObjcRef(&in_, v);
+	}
+	go_seq_send("vars.AnInterface", 1, &in_, &out_);
+	go_seq_free(&in_);
+	go_seq_free(&out_);
+}
+
+id<GoVarsI> GoVarsAnInterface() {
+	GoSeq in_ = {};
+	GoSeq out_ = {};
+	go_seq_send("vars.AnInterface", 2, &in_, &out_);
+	GoSeqRef* ret_ref = go_seq_readRef(&out_);
+	id<GoVarsI> ret = ret_ref.obj;
+	if (ret == NULL) {
+		ret = [[GoVarsI alloc] initWithRef:ret_ref];
+	}
+	go_seq_free(&in_);
+	go_seq_free(&out_);
+	return ret;
+}
+
+
+__attribute__((constructor)) static void init() {
+	go_seq_register_proxy("go.vars.I", proxyGoVarsI);
+}