func imports(info *pkg.Info) []string {
	us := info.Pkg()
	pkgs := make(map[string]bool)
	for _, pack := range []map[string]types.Type{info.Unpackers, info.Packers} {
		for _, p := range pack {
			named, ok := p.(*types.Named)
			if !ok {
				continue
			}
			pkg := named.Obj().Pkg()
			if pkg == nil || pkg == us {
				continue
			}
			pkgs[pkg.Path()] = true
		}
	}
	paths := make([]string, 0, len(pkgs))
	for p := range pkgs {
		paths = append(paths, p)
	}
	sort.Strings(paths)
	return paths
}
imports returns a slice of import paths to packages imported by the code
we are wrapping.
package codegen
import (
	"fmt"
	"go/types"
	"reflect"
	"sort"
	"strings"
	"text/template"
	"github.com/rgonomic/rgo/internal/pkg"
)
func GoFuncTemplate() *template.Template {
	return template.Must(template.New("Go func").Funcs(template.FuncMap{
		"imports":    imports,
		"varsOf":     varsOf,
		"go":         goParams,
		"anon":       anonymous,
		"types":      typeNames,
		"mangle":     pkg.Mangle,
		"unpackSEXP": unpackSEXPFuncGo,
		"packSEXP":   packSEXPFuncGo,
		"dec":        func(i int) int { return i - 1 },
	}).Parse(`{{$pkg := .Pkg}} 
package main
import "C"
import (
	"fmt"
	"unsafe"
{{with imports .}}{{range $p := .}}	"{{.}}"
{{end}}
{{end}}	"{{$pkg.Path}}"
)
{{$resultNeedsList := false}}{{range $func := .Funcs}}{{$params := varsOf $func.Signature.Params}}{{$results := varsOf $func.Signature.Results}}
func Wrapped_{{$func.Name}}({{go "_R_" $params}}) C.SEXP {
	defer func() {
		r := recover()
		if r != nil {
			err := C.CString(fmt.Sprint(r))
			C.R_error(err)
			C.free(unsafe.Pointer(err))
		}
	}()
	{{range $i, $p := $params}}_p{{$i}} := unpackSEXP{{mangle $p.Type}}(_R_{{$p.Name}})
	{{end}}{{with $results}}{{anon . "_r" false}} := {{end}}{{$pkg.Name}}.{{$func.Name}}({{anon $params "_p" false}}{{if $func.Signature.Variadic}}...{{end}})
	{{with $results}}return packSEXP_{{$func.Name}}({{anon . "_r" false}}){{else}}return C.R_NilValue{{end}}
}
{{if $results}}func packSEXP_{{$func.Name}}({{anon $results "p" true}}) C.SEXP {
{{$l := len $results -}}
{{- if eq $l 1 -}}
{{- $p := index $results 0}}	return packSEXP{{mangle $p.Type}}({{if $p.Name}}{{$p.Name}}{{else}}p0{{end -}})
{{- else}}{{$resultNeedsList = true}}	r := C.allocVector(C.VECSXP, {{len $results}})
	C.Rf_protect(r)
	defer C.Rf_unprotect(1)
	names := C.Rf_allocVector(C.STRSXP, {{len $results}})
	C.Rf_protect(names)
	defer C.Rf_unprotect(1)
{{range $i, $p := $results}}{{$res := printf "r%d" $i}}{{if $p.Name}}{{$res = $p.Name}}{{end}}	C.SET_STRING_ELT(names, {{$i}}, C.Rf_mkCharLenCE(C._GoStringPtr("{{$res}}"), {{len $res}}, C.CE_UTF8))
	C.SET_VECTOR_ELT(r, {{$i}}, packSEXP{{mangle $p.Type}}({{if $p.Name}}{{$p.Name}}{{else}}p{{$i}}{{end}}))
{{end}}	C.setAttrib(r, C.R_NamesSymbol, names)
	return r{{end}}
}
{{end}}{{end}}
{{  -}}
{{- .Unpackers.Types | unpackSEXP -}}
{{- .Packers.Types | packSEXP}}func main() {}
`))
}