bind: add support for Objective-C unsigned char to reverse bindings

Fixes golang/go#27723

Change-Id: I706f784736aea87e095a1dafdf9acf2b4590846c
GitHub-Last-Rev: 5e416702eb04dab5890487f3ee2a1581f394d8fd
GitHub-Pull-Request: golang/mobile#23
Reviewed-on: https://go-review.googlesource.com/135875
Reviewed-by: Elias Naur <elias.naur@gmail.com>
diff --git a/bind/genobjcw.go b/bind/genobjcw.go
index ba5d5de..7215ff9 100644
--- a/bind/genobjcw.go
+++ b/bind/genobjcw.go
@@ -131,7 +131,7 @@
 	// ret = ((<return type> (*)(id, SEL, <argument_types>))objc_msgSendSuper)(<struct objc_super>, <arguments>)
 	if f.Ret != nil {
 		switch f.Ret.Kind {
-		case objc.String, objc.Bool, objc.Data, objc.Int, objc.Uint, objc.Short, objc.Ushort, objc.Char, objc.Float, objc.Double, objc.Class, objc.Protocol:
+		case objc.String, objc.Bool, objc.Data, objc.Int, objc.Uint, objc.Short, objc.Ushort, objc.Char, objc.Uchar, objc.Float, objc.Double, objc.Class, objc.Protocol:
 		default:
 			// If support for struct results is added, objc_msgSend_stret must be used
 			panic("unsupported type kind - use objc_msgSend_stret?")
@@ -440,7 +440,7 @@
 		g.Printf("BOOL _%s = %s ? YES : NO;\n", name, name)
 	case objc.Data:
 		g.Printf("NSData *_%s = go_seq_to_objc_bytearray(%s, %d);\n", name, name, toCFlag(mode == modeRetained))
-	case objc.Int, objc.Uint, objc.Short, objc.Ushort, objc.Char, objc.Float, objc.Double:
+	case objc.Int, objc.Uint, objc.Short, objc.Ushort, objc.Char, objc.Uchar, objc.Float, objc.Double:
 		g.Printf("%s _%s = (%s)%s;\n", g.objcType(t), name, g.objcType(t), name)
 	case objc.Class, objc.Protocol:
 		g.Printf("GoSeqRef* %s_ref = go_seq_from_refnum(%s);\n", name, name)
@@ -459,7 +459,7 @@
 		g.Printf("nstring _%s = go_seq_from_objc_string(%s);\n", name, name)
 	case objc.Data:
 		g.Printf("nbyteslice _%s = go_seq_from_objc_bytearray(%s, %d);\n", name, name, toCFlag(mode == modeRetained))
-	case objc.Bool, objc.Int, objc.Uint, objc.Short, objc.Ushort, objc.Char, objc.Float, objc.Double:
+	case objc.Bool, objc.Int, objc.Uint, objc.Short, objc.Ushort, objc.Char, objc.Uchar, objc.Float, objc.Double:
 		g.Printf("%s _%s = (%s)%s;\n", g.cType(t), name, g.cType(t), name)
 	case objc.Protocol, objc.Class:
 		g.Printf("int _%s = go_seq_to_refnum(%s);\n", name, name)
@@ -479,7 +479,7 @@
 		g.Printf("if %s {\n", a.Name)
 		g.Printf("  _%s = %s(1)\n", a.Name, g.cgoType(a.Type))
 		g.Printf("}\n")
-	case objc.Int, objc.Uint, objc.Short, objc.Ushort, objc.Char, objc.Float, objc.Double:
+	case objc.Int, objc.Uint, objc.Short, objc.Ushort, objc.Char, objc.Uchar, objc.Float, objc.Double:
 		g.Printf("_%s := %s(%s)\n", a.Name, g.cgoType(a.Type), a.Name)
 	case objc.Protocol, objc.Class:
 		g.Printf("var _%s %s = _seq.NullRefNum\n", a.Name, g.cgoType(a.Type))
@@ -493,7 +493,7 @@
 
 func (g *ObjcWrapper) genRead(to, from string, t *objc.Type) {
 	switch t.Kind {
-	case objc.Int, objc.Uint, objc.Short, objc.Ushort, objc.Char, objc.Float, objc.Double:
+	case objc.Int, objc.Uint, objc.Uchar, objc.Short, objc.Ushort, objc.Char, objc.Float, objc.Double:
 		g.Printf("%s := %s(%s)\n", to, g.goType(t, false), from)
 	case objc.Bool:
 		g.Printf("%s := %s != 0\n", to, from)
@@ -736,6 +736,8 @@
 		return "bool"
 	case objc.Char:
 		return "byte"
+	case objc.Uchar:
+		return "uint8"
 	case objc.Float:
 		return "float32"
 	case objc.Double:
diff --git a/bind/testdata/objcw.go b/bind/testdata/objcw.go
index e1d104a..dadfd93 100644
--- a/bind/testdata/objcw.go
+++ b/bind/testdata/objcw.go
@@ -7,6 +7,7 @@
 import (
 	"ObjC/Foundation"
 	"ObjC/Foundation/NSMutableString"
+	"ObjC/NetworkExtension/NEPacket"
 	"ObjC/UIKit"
 )
 
@@ -50,3 +51,10 @@
 	// Pass slice from native to Go.
 	_ = mString.DataUsingEncoding(uint(NSUTF8StringEncoding))
 }
+
+// From <sys/socket.h>
+const PF_INET = 2
+
+func CallUcharFunction() {
+	_ = NEPacket.NewWithData(nil, uint8(PF_INET))
+}
diff --git a/bind/testdata/objcw.go.golden b/bind/testdata/objcw.go.golden
index d28a62b..0a0b7e6 100644
--- a/bind/testdata/objcw.go.golden
+++ b/bind/testdata/objcw.go.golden
@@ -41,6 +41,11 @@
 	Description() (string)
 }
 
+type NetworkExtension_NEPacket interface {
+	Hash() (uint)
+	Description() (string)
+}
+
 type Objc_GoNSDate interface {
 	Hash() (uint)
 	Description() (string)
@@ -69,6 +74,7 @@
 import "ObjC"
 import _seq "golang.org/x/mobile/bind/seq"
 import "ObjC/Foundation/NSMutableString"
+import "ObjC/NetworkExtension/NEPacket"
 
 type proxy interface { Bind_proxy_refnum__() int32 }
 
@@ -234,6 +240,41 @@
 }
 
 func init() {
+	NEPacket.NewWithData = func(data []byte, protocolFamily uint8) (ObjC.NetworkExtension_NEPacket) {
+		_data := fromSlice(data, false)
+		_protocolFamily := C.uchar(protocolFamily)
+		res := C.cproxy_s_NEPacket_NewWithData(_data, _protocolFamily)
+		var _res ObjC.NetworkExtension_NEPacket
+		_res_ref := _seq.FromRefNum(int32(res))
+		if _res_ref != nil {
+			if res < 0 { // go object
+				_res = _res_ref.Get().(ObjC.NetworkExtension_NEPacket)
+			} else { // foreign object
+				_res = (*proxy_class_NEPacket)(_res_ref)
+			}
+		}
+		return _res
+	}
+	
+}
+
+type proxy_class_NEPacket _seq.Ref
+
+func (p *proxy_class_NEPacket) Bind_proxy_refnum__() int32 { return (*_seq.Ref)(p).Bind_IncNum() }
+
+func (p *proxy_class_NEPacket) Hash() (uint) {
+	res := C.cproxy_NEPacket_Hash(C.int(p.Bind_proxy_refnum__()))
+	_res := uint(res)
+	return _res
+}
+
+func (p *proxy_class_NEPacket) Description() (string) {
+	res := C.cproxy_NEPacket_Description(C.int(p.Bind_proxy_refnum__()))
+	_res := decodeString(res)
+	return _res
+}
+
+func init() {
 }
 
 type proxy_class_GoNSDate _seq.Ref
@@ -549,6 +590,11 @@
 	return C.int32_t(_seq.ToRefNum(new(objc.GoUIResponder)))
 }
 
+//export proxyobjc__CallUcharFunction
+func proxyobjc__CallUcharFunction() {
+	objc.CallUcharFunction()
+}
+
 //export proxyobjc__CreateReadNSMutableString
 func proxyobjc__CreateReadNSMutableString() {
 	objc.CreateReadNSMutableString()