diff --git a/CHANGES.current b/CHANGES.current index 21f75ecf8..93e5fb943 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -5,6 +5,10 @@ See the RELEASENOTES file for a summary of changes in each release. Version 3.0.6 (in progress) =========================== +2015-03-02: ianlancetaylor + [Go] Add -cgo option, required for Go versions 1.5 and + later. + 2015-02-26: olly Fix segmentation fault when top==NULL, introduced by nested class handling (reported in issue#346 by Paweł Tomulik). diff --git a/Doc/Manual/Go.html b/Doc/Manual/Go.html index 895e6c581..175f22f26 100644 --- a/Doc/Manual/Go.html +++ b/Doc/Manual/Go.html @@ -111,6 +111,14 @@ swig -go -help Go specific options + +-cgo +Generate files to be used as input for the Go cgo tool. This + option is required for Go 1.5 and later, and works for Go 1.2 and + later. In the future this option will likely become the + default. + + -intgosize <s> Set the size for the Go type int. This controls the size @@ -171,8 +179,13 @@ swig -go -help

23.3.2 Go Output Files

-

When generating Go code, SWIG will generate the following - files:

+

There are two different approaches to generating output files, + controlled by SWIG's -cgo option. The -cgo option + works with Go version 1.2 or later. It is required when using Go + version 1.5 or later.

+ +

With or without the -cgo option, SWIG will generate the + following files when generating Go code:

+ +

When neither the -cgo nor the -gccgo option is + used, SWIG will also generate an additional file:

+ +

@@ -203,14 +225,33 @@ support for SWIG. To use it, put your SWIG interface into a file with the extension .swig, or, if you are wrapping C++ code, .swigcxx. Put that file in a GOPATH/src directory as usual for Go sources. Put other interface code in the same directory with extensions of .c and -.cxx. The go build command and go install commands will automatically -run SWIG for you and will build the interface code. +.cxx. The go build and go install commands will +automatically run SWIG for you and will build the interface code.

-You can also use SWIG directly yourself. When using the gc compiler -version 1.2 or later, or when using gccgo, the code generated by SWIG -can be linked directly into the Go program. A typical command +You can also use SWIG directly yourself. When using +the -cgo option, SWIG will generate files that can be used +directly by go build. Put your SWIG input file in a +directory under GOPATH/src, and give it a name that does not end in +.swig or .swigcxx. +

+ +
+% swig -go -cgo example.i
+% go install
+
+ +

+You will now have a Go package that you can import from other Go +packages as usual. +

+ +

+To use SWIG without the -cgo option, more steps are required. +Recall that this only works with Go versions before 1.5. When using +Go version 1.2 or later, or when using gccgo, the code generated by +SWIG can be linked directly into the Go program. A typical command sequence when using the gc compiler would look like this:

@@ -227,9 +268,8 @@ sequence when using the gc compiler would look like this:

You can also put the wrapped code into a shared library, and when -using the gc compiler before version 1.2 this is the only supported -option. A typical command sequence for this approach would look like -this: +using the Go versions before 1.2 this is the only supported option. A +typical command sequence for this approach would look like this:

diff --git a/Examples/Makefile.in b/Examples/Makefile.in
index 8aa1ecedf..47e2d7ca7 100644
--- a/Examples/Makefile.in
+++ b/Examples/Makefile.in
@@ -1752,15 +1752,18 @@ scilab_clean:
 
 GO = @GO@
 GOGCC = @GOGCC@
+GCCGO = @GCCGO@
 GO1 = @GO1@
 GO12 = @GO12@
 GO13 = @GO13@
+GO15 = @GO15@
 GOC = @GOC@
 GOOPT = @GOOPT@
+GCCGOOPT = @GCCGOOPT@
 GOVERSIONOPTION = @GOVERSIONOPTION@
 
 GOSWIGARG = `if $(GOGCC) ; then echo -gccgo; fi`
-GOCOMPILEARG = `if $(GOGCC) ; then echo -c -g; elif $(GO1) ; then echo tool $(GOC:c=g) ; fi` `if $(GO13) && ! $(GOGCC); then echo -pack ; fi`
+GOCOMPILEARG = `if $(GO1) ; then echo tool $(GOC:c=g) ; fi` `if $(GO13) || $(GO15); then echo -pack ; fi`
 
 GOSRCS = $(INTERFACE:.i=.go)
 GOCSRCS = $(INTERFACE:.i=_gc.c)
@@ -1769,7 +1772,9 @@ GOLD = $(GOC:c=l)
 GOTOOL = `if $(GO1) ; then echo go tool; fi`
 GOPACK = `if $(GO1) ; then echo go tool pack; else echo gopack; fi`
 
-GOPACKAGE = $(INTERFACE:.i=.a)
+GOPACKAGE = $(notdir $(INTERFACE:.i=.a))
+
+GOPATHDIR = gopath/src/$(INTERFACE:.i=)
 
 GOOBJEXT = $(GOC:c=)
 GOGCOBJS = $(GOSRCS:.go=.$(GOOBJEXT))
@@ -1779,19 +1784,21 @@ GOGCCOBJS = $(GOSRCS:.go=.@OBJEXT@)
 # Build a Go module (C)
 # ----------------------------------------------------------------
 
-go: $(SRCDIR_SRCS)
+go_nocgo: $(SRCDIR_SRCS)
 	$(SWIG) -go $(GOOPT) $(GOSWIGARG) $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH)
-	if $(GO12) || $(GO13) || $(GOGCC); then \
+	if $(GO12) || $(GO13) || $(GO15) || $(GOGCC); then \
 	  $(CC) -g -c $(CPPFLAGS) $(CFLAGS) $(SRCDIR_SRCS) $(ISRCS) $(INCLUDES); \
 	else \
 	  $(CC) -g -c $(CCSHARED) $(CPPFLAGS) $(CFLAGS) $(SRCDIR_SRCS) $(ISRCS) $(INCLUDES); \
 	  $(LDSHARED) $(CFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(LIBS) -o $(LIBPREFIX)$(TARGET)$(SO); \
 	fi
-	$(COMPILETOOL) $(GO) $(GOCOMPILEARG) -I . $(GOSRCS)
-	if ! $(GOGCC) ; then \
+	if $(GOGCC) ; then \
+	  $(COMPILETOOL) $(GCCGO) -g -c -I . $(GOSRCS); \
+	else \
+	  $(COMPILETOOL) $(GO) $(GOCOMPILEARG) -I . $(GOSRCS); \
 	  $(COMPILETOOL) $(GOTOOL) $(GOC) -I $${GOROOT:-`go env GOROOT`}/pkg/$${GOOS:-`go env GOOS`}_$${GOARCH:-`go env GOARCH`} $(GOCSRCS); \
 	  rm -f $(GOPACKAGE); \
-	  if $(GO13); then \
+	  if $(GO13) || $(GO15); then \
 	    cp $(GOGCOBJS) $(GOPACKAGE); \
 	    $(COMPILETOOL) $(GOPACK) r $(GOPACKAGE) $(GOCSRCS:.c=.$(GOOBJEXT)) $(OBJS) $(IOBJS); \
 	  elif $(GO12); then \
@@ -1801,12 +1808,54 @@ go: $(SRCDIR_SRCS)
 	  fi; \
 	fi
 	if test -f $(SRCDIR)$(RUNME).go; then \
-	  $(GO) $(GOCOMPILEARG) $(SRCDIR)$(RUNME).go; \
 	  if $(GOGCC) ; then \
-	    $(COMPILETOOL) $(GO) -o $(RUNME) $(RUNME).@OBJEXT@ $(GOGCCOBJS) $(OBJS) $(IOBJS); \
-	  elif $(GO12) || $(GO13); then \
+	    $(COMPILETOOL) $(GCCGO) -g -c $(SRCDIR)$(RUNME).go; \
+	    $(COMPILETOOL) $(GCCGO) -o $(RUNME) $(RUNME).@OBJEXT@ $(GOGCCOBJS) $(OBJS) $(IOBJS); \
+	  elif $(GO12) || $(GO13) || $(GO15); then \
+	    $(GO) $(GOCOMPILEARG) $(SRCDIR)$(RUNME).go; \
 	    $(COMPILETOOL) $(GOTOOL) $(GOLD) -linkmode external -extld "$(CC)" -extldflags "$(CFLAGS) $(LDFLAGS)" -o $(RUNME) $(RUNME).$(GOOBJEXT); \
 	  else \
+	    $(GO) $(GOCOMPILEARG) $(SRCDIR)$(RUNME).go; \
+	    $(COMPILETOOL) $(GOTOOL) $(GOLD) -r $${GOROOT:-`go env GOROOT`}/pkg/$${GOOS:-`go env GOOS`}_$${GOARCH:-`go env GOARCH`}:. -o $(RUNME) $(RUNME).$(GOOBJEXT); \
+	  fi; \
+	fi
+
+go: $(SRCDIR_SRCS)
+	$(SWIG) -go -cgo $(GOOPT) $(GOSWIGARG) $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH)
+	@mkdir gopath 2>/dev/null || true
+	@mkdir gopath/src 2>/dev/null || true
+	@mkdir gopath/src/$(INTERFACE:.i=) 2>/dev/null || true
+	rm -f $(GOPATHDIR)/*
+	cp $(ISRCS) $(GOPATHDIR)/
+	if test -f $(IWRAP:.i=.h); then \
+	  cp $(IWRAP:.i=.h) $(GOPATHDIR)/; \
+	fi
+	if test -n "$(SRCDIR_SRCS)"; then \
+	  cp $(SRCDIR_SRCS) $(GOPATHDIR)/; \
+	fi
+	cp $(GOSRCS) $(GOPATHDIR)/
+	GOPATH=`pwd`/gopath; \
+	export GOPATH; \
+	CGO_CPPFLAGS="$(CPPFLAGS) $(INCLUDES) -I `pwd`"; \
+	export CGO_CPPFLAGS; \
+	CGO_CFLAGS="$(CFLAGS)"; \
+	export CGO_CFLAGS; \
+	CGO_LDFLAGS="$(LDFLAGS) -lm"; \
+	export CGO_LDFLAGS; \
+	(cd $(GOPATHDIR)/ && $(COMPILETOOL) $(GO) build `if $(GOGCC); then echo -compiler=gccgo; fi` -o $(GOPACKAGE))
+	cp $(GOPATHDIR)/$(GOPACKAGE) $(dir $(INTERFACE))/$(GOPACKAGE)
+	if $(GOGCC); then \
+	  cp $(dir $(INTERFACE))/$(GOPACKAGE) $(dir $(INTERFACE))/$(GOPACKAGE:.a=.gox); \
+	fi
+	if test -f $(SRCDIR)$(RUNME).go; then \
+	  if $(GOGCC) ; then \
+	    $(COMPILETOOL) $(GCCGO) -c -g $(SRCDIR)$(RUNME).go; \
+	    $(COMPILETOOL) $(GCCGO) -o $(RUNME) $(RUNME).@OBJEXT@ $(dir $(INTERFACE))/$(GOPACKAGE); \
+	  elif $(GO12) || $(GO13) || $(GO15); then \
+	    $(COMPILETOOL) $(GO) $(GOCOMPILEARG) $(SRCDIR)$(RUNME).go; \
+	    $(COMPILETOOL) $(GOTOOL) $(GOLD) -linkmode external -extld "$(CC)" -extldflags "$(CFLAGS) $(LDFLAGS)" -o $(RUNME) $(RUNME).$(GOOBJEXT); \
+	  else \
+	    $(COMPILETOOL) $(GO) $(GOCOMPILEARG) $(SRCDIR)$(RUNME).go; \
 	    $(COMPILETOOL) $(GOTOOL) $(GOLD) -r $${GOROOT:-`go env GOROOT`}/pkg/$${GOOS:-`go env GOOS`}_$${GOARCH:-`go env GOARCH`}:. -o $(RUNME) $(RUNME).$(GOOBJEXT); \
 	  fi; \
 	fi
@@ -1815,9 +1864,9 @@ go: $(SRCDIR_SRCS)
 # Build a Go module (C++)
 # ----------------------------------------------------------------
 
-go_cpp: $(SRCDIR_SRCS)
+go_cpp_nocgo: $(SRCDIR_SRCS)
 	$(SWIG) -go -c++ $(GOOPT) $(GOSWIGARG) $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH)
-	if $(GO12) || $(GO13) || $(GOGCC); then \
+	if $(GO12) || $(GO13) || $(GO15) || $(GOGCC); then \
 	  if test -n "$(SRCDIR_CXXSRCS)$(SRCDIR_SRCS)"; then \
 	    $(CXX) -g -c $(CPPFLAGS) $(CXXFLAGS) $(SRCDIR_CXXSRCS) $(SRCDIR_SRCS) $(INCLUDES); \
 	  fi; \
@@ -1837,7 +1886,7 @@ go_cpp: $(SRCDIR_SRCS)
 	    -o $(addsuffix .$(GOOBJEXT),$(basename $f)) $f; \
 	  ) \
 	  rm -f $(GOPACKAGE); \
-	  if $(GO13); then \
+	  if $(GO13) || $(GO15); then \
 	    cp $(GOGCOBJS) $(GOPACKAGE); \
 	    $(COMPILETOOL) $(GOPACK) r $(GOPACKAGE) $(GOCSRCS:.c=.$(GOOBJEXT)) $(OBJS) $(IOBJS); \
 	  elif $(GO12); then \
@@ -1847,16 +1896,63 @@ go_cpp: $(SRCDIR_SRCS)
 	  fi; \
 	else \
 	  $(foreach f,$(GOSRCS), \
-	    $(COMPILETOOL) $(GO) $(GOCOMPILEARG) -I . -o $(addsuffix .@OBJEXT@,$(basename $f)) $f \
+	    $(COMPILETOOL) $(GCCGO) -g -c -I . -o $(addsuffix .@OBJEXT@,$(basename $f)) $f \
 	  ); \
 	fi
 	if test -f $(SRCDIR)$(RUNME).go; then \
-	  $(GO) $(GOCOMPILEARG) $(SRCDIR)$(RUNME).go; \
 	  if $(GOGCC) ; then \
-	    $(COMPILETOOL) $(GO) -o $(RUNME) $(RUNME).@OBJEXT@ $(GOGCCOBJS) $(OBJS) $(IOBJS) -lstdc++; \
-	  elif $(GO12) || $(GO13); then \
+	    $(COMPILETOOL) $(GCCGO) -g -c $(SRCDIR)$(RUNME).go; \
+	    $(COMPILETOOL) $(GCCGO) -o $(RUNME) $(RUNME).@OBJEXT@ $(GOGCCOBJS) $(OBJS) $(IOBJS) -lstdc++; \
+	  elif $(GO12) || $(GO13) || $(GO15); then \
+	    $(GO) $(GOCOMPILEARG) $(SRCDIR)$(RUNME).go; \
 	    $(COMPILETOOL) $(GOTOOL) $(GOLD) -linkmode external -extld "$(CXX)" -extldflags "$(CXXFLAGS) $(LDFLAGS)" -o $(RUNME) $(RUNME).$(GOOBJEXT); \
 	  else \
+	    $(GO) $(GOCOMPILEARG) $(SRCDIR)$(RUNME).go; \
+	    $(COMPILETOOL) $(GOTOOL) $(GOLD) -r $${GOROOT:-`go env GOROOT`}/pkg/$${GOOS:-`go env GOOS`}_$${GOARCH:-`go env GOARCH`}:. -o $(RUNME) $(RUNME).$(GOOBJEXT); \
+	  fi; \
+	fi
+
+go_cpp: $(SRCDIR_SRCS)
+	$(SWIG) -go -c++ -cgo $(GOOPT) $(GOSWIGARG) $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH)
+	@mkdir gopath 2>/dev/null || true
+	@mkdir gopath/src 2>/dev/null || true
+	@mkdir gopath/src/$(INTERFACE:.i=) 2>/dev/null || true
+	rm -f $(GOPATHDIR)/*
+	cp $(ICXXSRCS) $(GOPATHDIR)/
+	if test -f $(IWRAP:.i=.h); then \
+	  cp $(IWRAP:.i=.h) $(GOPATHDIR)/; \
+	fi
+	if test -n "$(SRCDIR_CXXSRCS)"; then \
+	  cp $(SRCDIR_CXXSRCS) $(GOPATHDIR)/; \
+	fi
+	if test -n "$(SRCDIR_SRCS)"; then \
+	  cp $(SRCDIR_SRCS) $(GOPATHDIR)/; \
+	fi
+	cp $(GOSRCS) $(GOPATHDIR)/
+	GOPATH=`pwd`/gopath; \
+	export GOPATH; \
+	CGO_CPPFLAGS="$(CPPFLAGS) $(INCLUDES) -I `pwd`"; \
+	export CGO_CPPFLAGS; \
+	CGO_CFLAGS="$(CFLAGS)"; \
+	export CGO_CFLAGS; \
+	CGO_CXXFLAGS="$(CXXFLAGS)"; \
+	export CGO_CXXFLAGS; \
+	CGO_LDFLAGS="$(LDFLAGS) -lm"; \
+	export CGO_LDFLAGS; \
+	(cd $(GOPATHDIR) && $(COMPILETOOL) $(GO) build `if $(GOGCC); then echo -compiler=gccgo; fi` -o $(GOPACKAGE))
+	cp $(GOPATHDIR)/$(GOPACKAGE) $(dir $(INTERFACE))/$(GOPACKAGE)
+	if $(GOGCC); then \
+	  cp $(dir $(INTERFACE))/$(GOPACKAGE) $(dir $(INTERFACE))/$(GOPACKAGE:.a=.gox); \
+	fi
+	if test -f $(SRCDIR)$(RUNME).go; then \
+	  if $(GOGCC) ; then \
+	    $(COMPILETOOL) $(GCCGO) -g -c $(SRCDIR)$(RUNME).go; \
+	    $(COMPILETOOL) $(GCCGO) -o $(RUNME) $(RUNME).@OBJEXT@ $(dir $(INTERFACE))/$(GOPACKAGE) -lstdc++; \
+	  elif $(GO12) || $(GO13) || $(GO15); then \
+	    $(COMPILETOOL) $(GO) $(GOCOMPILEARG) $(SRCDIR)$(RUNME).go; \
+	    $(COMPILETOOL) $(GOTOOL) $(GOLD) -linkmode external -extld "$(CXX)" -extldflags "$(CXXFLAGS) $(LDFLAGS)" -o $(RUNME) $(RUNME).$(GOOBJEXT); \
+	  else \
+	    $(COMPILETOOL) $(GO) $(GOCOMPILEARG) $(SRCDIR)$(RUNME).go; \
 	    $(COMPILETOOL) $(GOTOOL) $(GOLD) -r $${GOROOT:-`go env GOROOT`}/pkg/$${GOOS:-`go env GOOS`}_$${GOARCH:-`go env GOARCH`}:. -o $(RUNME) $(RUNME).$(GOOBJEXT); \
 	  fi; \
 	fi
@@ -1880,7 +1976,8 @@ go_version:
 # -----------------------------------------------------------------
 
 go_clean:
-	rm -f *_wrap* *_gc* .~* $(RUNME) $(GOSRCS)
+	rm -f *_wrap* *_gc* *.gox .~* $(RUNME) $(GOSRCS)
+	rm -rf gopath
 	rm -f core @EXTRA_CLEAN@
 	rm -f *.@OBJEXT@ *.[568] *.a *@SO@
 
diff --git a/Examples/test-suite/go/Makefile.in b/Examples/test-suite/go/Makefile.in
index b4747601c..3c99a0879 100644
--- a/Examples/test-suite/go/Makefile.in
+++ b/Examples/test-suite/go/Makefile.in
@@ -5,13 +5,15 @@
 LANGUAGE	= go
 GO		= @GO@
 GOGCC		= @GOGCC@
+GCCGO		= @GCCGO@
 GO1		= @GO1@
 GO12		= @GO12@
 GO13		= @GO13@
+GO15		= @GO15@
 GOC		= @GOC@
 SCRIPTSUFFIX	= _runme.go
 
-GOCOMPILEARG = `if $(GOGCC) ; then echo -c -g; elif $(GO1) ; then echo tool $(GOC:c=g) ; fi`
+GOCOMPILEARG = `if $(GO1) ; then echo tool $(GOC:c=g) ; fi`
 GOLD = $(GOC:c=l)
 GOTOOL = `if $(GO1) ; then echo go tool; fi`
 GOPACK = `if $(GO1) ; then echo go tool pack; else echo gopack; fi`
@@ -20,9 +22,10 @@ GOOBJEXT = $(GOC:c=)
 
 SO = @SO@
 
-srcdir       = @srcdir@
-top_srcdir   = @top_srcdir@
-top_builddir = @top_builddir@
+srcdir         = @srcdir@
+top_srcdir     = @top_srcdir@
+top_builddir   = @top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
 
 CPP_TEST_CASES = \
 	go_inout \
@@ -33,6 +36,8 @@ MULTI_CPP_TEST_CASES = \
 
 include $(srcdir)/../common.mk
 
+INCLUDES = -I$(abs_top_srcdir)/$(EXAMPLES)/$(TEST_SUITE)
+
 .SUFFIXES: .cpptest .ctest .multicpptest
 
 # Rules for the different types of tests
@@ -40,17 +45,37 @@ include $(srcdir)/../common.mk
 	$(setup)
 	+$(swig_and_compile_cpp)
 	$(run_testcase_cpp)
+	if ! $(GO15); then \
+	  $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile SRCDIR="$(SRCDIR)" CXXSRCS="$(CXXSRCS)" \
+	  SWIG_LIB="$(SWIG_LIB)" SWIG="$(SWIG)" \
+	  INCLUDES="$(INCLUDES)" SWIGOPT="$(SWIGOPT)" NOLINK=true \
+	  TARGET="$(TARGETPREFIX)$*$(TARGETSUFFIX)" INTERFACEDIR="$(INTERFACEDIR)" INTERFACE="$*.i" \
+	  $(LANGUAGE)$(VARIANT)_cpp_nocgo; \
+	  $(run_testcase_cpp); \
+	fi
 
 %.ctest:
 	$(setup)
 	+$(swig_and_compile_c)
 	$(run_testcase)
+	if ! $(GO15); then \
+	  $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile SRCDIR="$(SRCDIR)" CSRCS="$(CSRCS)" \
+	  SWIG_LIB="$(SWIG_LIB)" SWIG="$(SWIG)" \
+	  INCLUDES="$(INCLUDES)" SWIGOPT="$(SWIGOPT)" NOLINK=true \
+	  TARGET="$(TARGETPREFIX)$*$(TARGETSUFFIX)" INTERFACEDIR="$(INTERFACEDIR)" INTERFACE="$*.i" \
+	  $(LANGUAGE)$(VARIANT)_nocgo; \
+	  $(run_testcase); \
+	fi
 
 %.multicpptest:
 	$(setup)
 	+$(swig_and_compile_multi_cpp)
 	$(run_multi_testcase)
 
+li_windows.cpptest:
+	# Does not work because go build won't build li_windows.go,
+	# because file names with "windows" are only built on Windows.
+
 multi_import.multicpptest:
 	$(setup)
 	for f in multi_import_b multi_import_a; do \
@@ -65,6 +90,7 @@ multi_import.multicpptest:
 go_subdir_import.multicpptest:
 	$(setup)
 	mkdir -p testdir/go_subdir_import/
+	mkdir -p gopath/src/testdir/go_subdir_import/
 	$(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile SRCDIR="$(SRCDIR)" CXXSRCS="$(CXXSRCS)" \
 	SWIG_LIB="$(SWIG_LIB)" SWIG="$(SWIG)" LIBS='$(LIBS)' \
 	INTERFACEPATH="$(SRCDIR)$(INTERFACEDIR)go_subdir_import_b.i" \
@@ -80,19 +106,24 @@ go_subdir_import.multicpptest:
 	  $(LANGUAGE)$(VARIANT)_cpp; \
 	done
 	if $(GOGCC); then \
-	  cp testdir/go_subdir_import/*.@OBJEXT@ .; \
+	  cp gopath/src/testdir/go_subdir_import/go_subdir_import_b/go_subdir_import_b.a gopath/src/testdir/go_subdir_import/go_subdir_import_b.gox; \
+	  cp gopath/src/testdir/go_subdir_import/go_subdir_import_b/go_subdir_import_b.a .; \
+	  cp gopath/src/testdir/go_subdir_import/go_subdir_import_c/go_subdir_import_c.a gopath/src/testdir/go_subdir_import/go_subdir_import_c.gox; \
+	  cp gopath/src/testdir/go_subdir_import/go_subdir_import_c/go_subdir_import_c.a testdir/go_subdir_import/; \
 	fi
 	$(run_multi_testcase)
 
 # Runs the testcase.
 run_testcase = \
 	if test -f $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX); then \
-	  $(COMPILETOOL) $(GO) $(GOCOMPILEARG) -I . $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) && \
 	  if $(GOGCC) ; then \
-	    $(COMPILETOOL) $(GO) -o $*_runme $(SCRIPTPREFIX)$*_runme.@OBJEXT@ $*.@OBJEXT@ $*_wrap.@OBJEXT@; \
-	  elif $(GO12) || $(GO13); then \
+	    $(COMPILETOOL) $(GCCGO) -c -g -I . $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) && \
+	    $(COMPILETOOL) $(GCCGO) -o $*_runme $(SCRIPTPREFIX)$*_runme.@OBJEXT@ $*.a; \
+	  elif $(GO12) || $(GO13) || $(GO15); then \
+	    $(COMPILETOOL) $(GO) $(GOCOMPILEARG) -I . $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) && \
 	    $(COMPILETOOL) $(GOTOOL) $(GOLD) -linkmode external -extld $(CC) -extldflags "$(CFLAGS)" -o $*_runme $(SCRIPTPREFIX)$*_runme.$(GOOBJEXT); \
 	  else \
+	    $(COMPILETOOL) $(GO) $(GOCOMPILEARG) -I . $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) && \
 	    $(COMPILETOOL) $(GOTOOL) $(GOLD) -L . -r $${GOROOT:-`go env GOROOT`}/pkg/$${GOOS:-`go env GOOS`}_$${GOARCH:-`go env GOARCH`}:. -o $*_runme $(SCRIPTPREFIX)$*_runme.$(GOOBJEXT); \
 	  fi && \
 	  env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH $(RUNTOOL) ./$*_runme; \
@@ -100,12 +131,14 @@ run_testcase = \
 
 run_testcase_cpp = \
 	if test -f $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX); then \
-	  $(COMPILETOOL) $(GO) $(GOCOMPILEARG) -I . $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) && \
 	  if $(GOGCC) ; then \
-	    $(COMPILETOOL) $(GO) -o $*_runme $(SCRIPTPREFIX)$*_runme.@OBJEXT@ $*.@OBJEXT@ $*_wrap.@OBJEXT@ -lstdc++; \
-	  elif $(GO12) || $(GO13); then \
+	    $(COMPILETOOL) $(GCCGO) -c -g -I . $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) && \
+	    $(COMPILETOOL) $(GCCGO) -o $*_runme $(SCRIPTPREFIX)$*_runme.@OBJEXT@ $*.a -lstdc++; \
+	  elif $(GO12) || $(GO13) || $(GO15); then \
+	    $(COMPILETOOL) $(GO) $(GOCOMPILEARG) -I . $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) && \
 	    $(COMPILETOOL) $(GOTOOL) $(GOLD) -linkmode external -extld $(CXX) -extldflags "$(CXXFLAGS)" -o $*_runme $(SCRIPTPREFIX)$*_runme.$(GOOBJEXT); \
 	  else \
+	    $(COMPILETOOL) $(GO) $(GOCOMPILEARG) -I . $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) && \
 	    $(COMPILETOOL) $(GOTOOL) $(GOLD) -L . -r $${GOROOT:-`go env GOROOT`}/pkg/$${GOOS:-`go env GOOS`}_$${GOARCH:-`go env GOARCH`}:. -o $*_runme $(SCRIPTPREFIX)$*_runme.$(GOOBJEXT); \
 	  fi && \
 	  env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH $(RUNTOOL) ./$*_runme; \
@@ -113,29 +146,38 @@ run_testcase_cpp = \
 
 run_multi_testcase = \
 	if test -f $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX); then \
-	  $(COMPILETOOL) $(GO) $(GOCOMPILEARG) -I . $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) && \
 	  if $(GOGCC) ; then \
+	    $(COMPILETOOL) $(GCCGO) -c -g -I . -I gopath/src $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) && \
 	    files=`cat $(top_srcdir)/$(EXAMPLES)/$(TEST_SUITE)/$*.list`; \
-	    $(COMPILETOOL) $(GO) -o $*_runme $(SCRIPTPREFIX)$*_runme.@OBJEXT@ `for f in $$files; do echo $$f.@OBJEXT@ $${f}_wrap.@OBJEXT@; done` -lstdc++; \
-	  elif $(GO12) || $(GO13); then \
+	    $(COMPILETOOL) $(GCCGO) -o $*_runme $(SCRIPTPREFIX)$*_runme.@OBJEXT@ `for f in $$files; do echo $$f.a; done` -lstdc++; \
+	  elif $(GO12) || $(GO13) || $(GO15); then \
+	    $(COMPILETOOL) $(GO) $(GOCOMPILEARG) -I . $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) && \
 	    $(COMPILETOOL) $(GOTOOL) $(GOLD) -L . -linkmode external -extld $(CXX) -extldflags "$(CXXFLAGS)" -o $*_runme $(SCRIPTPREFIX)$*_runme.$(GOOBJEXT); \
 	  else \
+	    $(COMPILETOOL) $(GO) $(GOCOMPILEARG) -I . $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) && \
 	    $(COMPILETOOL) $(GOTOOL) $(GOLD) -L . -r $${GOROOT:-`go env GOROOT`}/pkg/$${GOOS:-`go env GOOS`}_$${GOARCH:-`go env GOARCH`}:. -o $*_runme $(SCRIPTPREFIX)$*_runme.$(GOOBJEXT); \
 	  fi && \
 	  env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH $(RUNTOOL) ./$*_runme; \
 	fi
 
 %.clean:
-	@rm -f $*.go $*_gc.c $*_wrap.* $*_runme
+	@rm -rf $*.go $*_gc.c $*_wrap.* $*_runme $*.gox $*.a
 
 clean:
 	$(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile SRCDIR="$(SRCDIR)" go_clean
-	rm -f mod_a.go mod_b.go imports_a.go imports_b.go
-	rm -f clientdata_prop_a.go clientdata_prop_b.go
-	rm -f multi_import_a.go multi_import_b.go
-	rm -rf go_subdir_import_a.go testdir
-	rm -f packageoption_a.go packageoption_b.go packageoption_c.go
-	rm -f import_stl_a.go import_stl_b.go
+	rm -f mod_a.go mod_a.gox mod_b.go mod_b.gox
+	rm -f imports_a.go imports_a.gox imports_b.go imports_b.gox
+	rm -f clientdata_prop_a.go clientdata_prop_a.gox
+	rm -f clientdata_prop_b.go clientdata_prop_b.gox
+	rm -f multi_import_a.go multi_import_a.gox
+	rm -f multi_import_b.go multi_import_b.gox
+	rm -rf go_subdir_import_a.go go_subdir_import_a.gox testdir
+	rm -f packageoption_a.go packageoption_a.gox
+	rm -f packageoption_b.go packageoption_b.gox
+	rm -f packageoption_c.go packageoption_c.gox
+	rm -f import_stl_a.go import_stl_a.gox
+	rm -f import_stl_b.go import_stl_b.gox
+	rm -rf gopath
 
 cvsignore:
 	@echo '*_gc.c *_wrap.* *.so *.dll *.exp *.lib'
diff --git a/Examples/test-suite/go_subdir_import_a.i b/Examples/test-suite/go_subdir_import_a.i
index 72b28786e..3fc36e6f9 100644
--- a/Examples/test-suite/go_subdir_import_a.i
+++ b/Examples/test-suite/go_subdir_import_a.i
@@ -20,12 +20,12 @@
 %{
 class ObjC {
  public:
-  int getInt() const;
+  virtual int getInt() const;
 };
 
 class ObjB {
  public:
-  int getInt() const;
+  virtual int getInt() const;
 };
 %}
 
diff --git a/Examples/test-suite/go_subdir_import_b.i b/Examples/test-suite/go_subdir_import_b.i
index b87f7cf3c..42544822e 100644
--- a/Examples/test-suite/go_subdir_import_b.i
+++ b/Examples/test-suite/go_subdir_import_b.i
@@ -4,7 +4,7 @@
 %inline %{
 class ObjB {
  public:
-  int getInt() const {
+  virtual int getInt() const {
     return 27;
   }
 };
diff --git a/Examples/test-suite/testdir/go_subdir_import/go_subdir_import_c.i b/Examples/test-suite/testdir/go_subdir_import/go_subdir_import_c.i
index 2c2c2e1fe..dff269c3f 100644
--- a/Examples/test-suite/testdir/go_subdir_import/go_subdir_import_c.i
+++ b/Examples/test-suite/testdir/go_subdir_import/go_subdir_import_c.i
@@ -4,7 +4,7 @@
 %inline %{
 class ObjC {
  public:
-  int getInt() const {
+  virtual int getInt() const {
     return 18;
   }
 };
diff --git a/Lib/go/go.swg b/Lib/go/go.swg
index d38623b4a..35f914c5b 100644
--- a/Lib/go/go.swg
+++ b/Lib/go/go.swg
@@ -533,7 +533,7 @@
 %typemap(directorin) enum SWIGTYPE & (intgo e)
 %{
   e = (intgo)$1;
-  $input = &e;
+  $input = ($1_ltype)&e;
 %}
 
 %typemap(godirectorin) enum SWIGTYPE & ""
diff --git a/Lib/go/goruntime.swg b/Lib/go/goruntime.swg
index f76da9c78..d776e414a 100644
--- a/Lib/go/goruntime.swg
+++ b/Lib/go/goruntime.swg
@@ -19,21 +19,45 @@ static void Swig_free(void* p) {
 
 %}
 
+#if SWIGGO_CGO
+%insert(cgo_comment_typedefs) %{
+#include 
+%}
+#endif
+
 #if SWIGGO_INTGO_SIZE == 32
 %insert(runtime) %{
 typedef int intgo;
 typedef unsigned int uintgo;
 %}
+#if SWIGGO_CGO
+%insert(cgo_comment_typedefs) %{
+typedef int intgo;
+typedef unsigned int uintgo;
+%}
+#endif
 #elif SWIGGO_INTGO_SIZE == 64
 %insert(runtime) %{
 typedef long long intgo;
 typedef unsigned long long uintgo;
 %}
+#if SWIGGO_CGO
+%insert(cgo_comment_typedefs) %{
+typedef long long intgo;
+typedef unsigned long long uintgo;
+%}
+#endif
 #else
 %insert(runtime) %{
 typedef ptrdiff_t intgo;
 typedef size_t uintgo;
 %}
+#if SWIGGO_CGO
+%insert(cgo_comment_typedefs) %{
+typedef ptrdiff_t intgo;
+typedef size_t uintgo;
+%}
+#endif
 #endif
 
 %insert(runtime) %{
@@ -43,6 +67,17 @@ typedef struct { void* array; intgo len; intgo cap; } _goslice_;
 
 %}
 
+#ifdef SWIGGO_CGO
+
+%insert(cgo_comment_typedefs) %{
+
+typedef struct { char *p; intgo n; } _gostring_;
+typedef struct { void* array; intgo len; intgo cap; } _goslice_;
+
+%}
+
+#endif
+
 #ifndef SWIGGO_GCCGO
 /* Boilerplate for C/C++ code when using 6g/8g.  This code is compiled
    with gcc.  */
@@ -98,6 +133,8 @@ static void _swig_gopanic(const char *p) {
 
 %}
 
+#if !SWIGGO_CGO
+
 /* Boilerplate for C code when using 6g/8g.  This code is compiled
    with 6c/8c.  */
 %insert(gc_header) %{
@@ -111,6 +148,8 @@ void *·_cgo_runtime_cgocall = &cgocall;
 
 %}
 
+#endif
+
 #else
 
 /* Boilerplate for C/C++ code when using gccgo.  */
@@ -122,6 +161,17 @@ extern "C" {
 #endif
 extern void *_cgo_allocate(size_t);
 extern void _cgo_panic(const char *);
+#ifdef __cplusplus
+}
+#endif
+
+#define _swig_goallocate _cgo_allocate
+#define _swig_gopanic _cgo_panic
+%}
+
+#if !SWIGGO_CGO
+
+%insert(runtime) %{
 
 /* Implementations of SwigCgocall and friends for different versions
    of gccgo.  The Go code will call these functions using C names with
@@ -130,6 +180,10 @@ extern void _cgo_panic(const char *);
    version.  We assume that the version of gcc used to compile this
    file is the same as the version of gccgo.  */
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #define SWIG_GCC_VERSION \
   (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
 
@@ -184,13 +238,12 @@ void SwigCgocallBackDone() {
 }
 #endif
 
-#define _swig_goallocate _cgo_allocate
-#define _swig_gopanic _cgo_panic
-
 %}
 
 #endif
 
+#endif
+
 %insert(runtime) %{
 
 static _gostring_ _swig_makegostring(const char *p, size_t l) {
@@ -209,9 +262,11 @@ static _gostring_ _swig_makegostring(const char *p, size_t l) {
 
 %go_import("unsafe", _ "runtime/cgo")
 
+#if !SWIGGO_CGO
 %insert(go_header) %{
 var _cgo_runtime_cgocall func(unsafe.Pointer, uintptr)
 %}
+#endif
 
 #else
 
@@ -231,6 +286,8 @@ type _ unsafe.Pointer
 
 %}
 
+#if !SWIGGO_CGO
+
 /* Swig_always_false is used to conditionally assign parameters to
    Swig_escape_val so that the compiler thinks that they escape.  We
    only assign them if Swig_always_false is true, which it never is.
@@ -241,6 +298,8 @@ var Swig_escape_always_false bool
 var Swig_escape_val interface{}
 %}
 
+#endif
+
 /* Function pointers are translated by the code in go.cxx into
    _swig_fnptr.  Member pointers are translated to _swig_memberptr.  */
 
diff --git a/Source/Modules/go.cxx b/Source/Modules/go.cxx
index 92d857c56..0d349bd22 100644
--- a/Source/Modules/go.cxx
+++ b/Source/Modules/go.cxx
@@ -115,6 +115,8 @@ class GO:public Language {
   String *package;
   // SWIG module name.
   String *module;
+  // Flag for generating cgo input files.
+  bool cgo_flag;
   // Flag for generating gccgo output.
   bool gccgo_flag;
   // Prefix to use with gccgo.
@@ -150,6 +152,8 @@ class GO:public Language {
   File *f_gc_runtime;
   File *f_gc_header;
   File *f_gc_wrappers;
+  File *f_cgo_comment;
+  File *f_cgo_comment_typedefs;
 
   // True if we imported a module.
   bool saw_import;
@@ -195,6 +199,7 @@ class GO:public Language {
 public:
   GO():package(NULL),
      module(NULL),
+     cgo_flag(false),
      gccgo_flag(false),
      go_prefix(NULL),
      prefix_option(NULL),
@@ -219,6 +224,8 @@ public:
      f_gc_runtime(NULL),
      f_gc_header(NULL),
      f_gc_wrappers(NULL),
+     f_cgo_comment(NULL),
+     f_cgo_comment_typedefs(NULL),
      saw_import(false),
      imported_package(NULL),
      interfaces(NULL),
@@ -231,7 +238,8 @@ public:
      undefined_enum_types(NULL),
      undefined_types(NULL),
      defined_types(NULL),
-     go_imports(NULL) {
+     go_imports(NULL),
+     unique_id(NULL) {
     director_multiple_inheritance = 1;
     director_language = 1;
     director_prot_ctor_code = NewString("_swig_gopanic(\"accessing abstract class or protected constructor\");");
@@ -258,6 +266,9 @@ private:
 	  } else {
 	    Swig_arg_error();
 	  }
+	} else if (strcmp(argv[i], "-cgo") == 0) {
+	  Swig_mark_arg(i);
+	  cgo_flag = true;
 	} else if (strcmp(argv[i], "-gccgo") == 0) {
 	  Swig_mark_arg(i);
 	  gccgo_flag = true;
@@ -327,6 +338,10 @@ private:
     // Add preprocessor symbol to parser.
     Preprocessor_define("SWIGGO 1", 0);
 
+    if (cgo_flag) {
+      Preprocessor_define("SWIGGO_CGO 1", 0);
+    }
+
     if (gccgo_flag) {
       Preprocessor_define("SWIGGO_GCCGO 1", 0);
     }
@@ -474,7 +489,7 @@ private:
       SWIG_exit(EXIT_FAILURE);
     }
 
-    if (!gccgo_flag) {
+    if (!gccgo_flag && !cgo_flag) {
       f_gc_begin = NewFile(gc_filename, "w", SWIG_output_files());
       if (!f_gc_begin) {
 	FileErrorDisplay(gc_filename);
@@ -492,11 +507,15 @@ private:
     f_go_header = NewString("");
     f_go_wrappers = NewString("");
     f_go_directors = NewString("");
-    if (!gccgo_flag) {
+    if (!gccgo_flag && !cgo_flag) {
       f_gc_runtime = NewString("");
       f_gc_header = NewString("");
       f_gc_wrappers = NewString("");
     }
+    if (cgo_flag) {
+      f_cgo_comment = NewString("");
+      f_cgo_comment_typedefs = NewString("");
+    }
 
     Swig_register_filebyname("begin", f_c_begin);
     Swig_register_filebyname("runtime", f_c_runtime);
@@ -511,12 +530,16 @@ private:
     Swig_register_filebyname("go_header", f_go_header);
     Swig_register_filebyname("go_wrapper", f_go_wrappers);
     Swig_register_filebyname("go_director", f_go_directors);
-    if (!gccgo_flag) {
+    if (!gccgo_flag && !cgo_flag) {
       Swig_register_filebyname("gc_begin", f_gc_begin);
       Swig_register_filebyname("gc_runtime", f_gc_runtime);
       Swig_register_filebyname("gc_header", f_gc_header);
       Swig_register_filebyname("gc_wrapper", f_gc_wrappers);
     }
+    if (cgo_flag) {
+      Swig_register_filebyname("cgo_comment", f_cgo_comment);
+      Swig_register_filebyname("cgo_comment_typedefs", f_cgo_comment_typedefs);
+    }
 
     Swig_banner(f_c_begin);
     if (CPlusPlus) {
@@ -549,18 +572,28 @@ private:
     Swig_banner(f_go_begin);
     Printf(f_go_begin, "\n// source: %s\n", swig_filename);
 
-    if (!gccgo_flag && soname) {
+    if (!gccgo_flag && !cgo_flag && soname) {
       Swig_banner(f_gc_begin);
       Printf(f_gc_begin, "\n/* source: %s */\n\n", swig_filename);
       Printf(f_gc_begin, "\n/* This file should be compiled with 6c/8c.  */\n");
       Printf(f_gc_begin, "#pragma dynimport _ _ \"%s\"\n", soname);
     }
 
+    if (cgo_flag) {
+      Printv(f_cgo_comment_typedefs, "/*\n", NULL);
+
+      // The cgo program defines the intgo type after our function
+      // definitions, but we want those definitions to be able to use
+      // intgo also.
+      Printv(f_cgo_comment_typedefs, "#define intgo swig_intgo\n", NULL);
+      Printv(f_cgo_comment_typedefs, "typedef void *swig_voidp;\n", NULL);
+    }
+
     // Output module initialization code.
 
     Printf(f_go_begin, "\npackage %s\n\n", getModuleName(package));
 
-    if (gccgo_flag) {
+    if (gccgo_flag && !cgo_flag) {
       Printf(f_go_runtime, "func SwigCgocall()\n");
       Printf(f_go_runtime, "func SwigCgocallDone()\n");
       Printf(f_go_runtime, "func SwigCgocallBack()\n");
@@ -632,9 +665,21 @@ private:
     // End the extern "C".
     Printv(f_c_wrappers, "#ifdef __cplusplus\n", "}\n", "#endif\n\n", NULL);
 
+    if (cgo_flag) {
+      // End the cgo comment.
+      Printv(f_cgo_comment, "#undef intgo\n", NULL);
+      Printv(f_cgo_comment, "*/\n", NULL);
+      Printv(f_cgo_comment, "import \"C\"\n", NULL);
+      Printv(f_cgo_comment, "\n", NULL);
+    }
+
     Dump(f_c_runtime, f_c_begin);
     Dump(f_c_wrappers, f_c_begin);
     Dump(f_c_init, f_c_begin);
+    if (cgo_flag) {
+      Dump(f_cgo_comment_typedefs, f_go_begin);
+      Dump(f_cgo_comment, f_go_begin);
+    }
     Dump(f_go_imports, f_go_begin);
     Dump(f_go_header, f_go_begin);
     Dump(f_go_runtime, f_go_begin);
@@ -642,7 +687,7 @@ private:
     if (directorsEnabled()) {
       Dump(f_go_directors, f_go_begin);
     }
-    if (!gccgo_flag) {
+    if (!gccgo_flag && !cgo_flag) {
       Dump(f_gc_header, f_gc_begin);
       Dump(f_gc_runtime, f_gc_begin);
       Dump(f_gc_wrappers, f_gc_begin);
@@ -657,15 +702,19 @@ private:
     Delete(f_go_header);
     Delete(f_go_wrappers);
     Delete(f_go_directors);
-    if (!gccgo_flag) {
+    if (!gccgo_flag && !cgo_flag) {
       Delete(f_gc_runtime);
       Delete(f_gc_header);
       Delete(f_gc_wrappers);
     }
+    if (cgo_flag) {
+      Delete(f_cgo_comment);
+      Delete(f_cgo_comment_typedefs);
+    }
 
     Delete(f_c_begin);
     Delete(f_go_begin);
-    if (!gccgo_flag) {
+    if (!gccgo_flag && !cgo_flag) {
       Delete(f_gc_begin);
     }
 
@@ -945,24 +994,33 @@ private:
 
     assert(result);
 
-    int r = goFunctionWrapper(n, name, go_name, overname, wname, base, parms, result, is_static);
-    if (r != SWIG_OK) {
-      return r;
-    }
+    int ret = SWIG_OK;
 
-    if (!gccgo_flag) {
-      r = gcFunctionWrapper(wname);
+    if (cgo_flag) {
+      int r = makeCgoWrappers(n, go_name, overname, wname, base, parms, result, is_static);
       if (r != SWIG_OK) {
-	return r;
-      }
-      r = gccFunctionWrapper(n, base, wname, parms, result);
-      if (r != SWIG_OK) {
-	return r;
+	ret = r;
       }
     } else {
-      r = gccgoFunctionWrapper(n, base, wname, parms, result);
+      int r = goFunctionWrapper(n, name, go_name, overname, wname, base, parms, result, is_static);
       if (r != SWIG_OK) {
-	return r;
+	ret = r;
+      }
+
+      if (!gccgo_flag) {
+	r = gcFunctionWrapper(wname);
+	if (r != SWIG_OK) {
+	  ret = r;
+	}
+	r = gccFunctionWrapper(n, base, wname, parms, result);
+	if (r != SWIG_OK) {
+	  ret = r;
+	}
+      } else {
+	r = gccgoFunctionWrapper(n, base, wname, parms, result);
+	if (r != SWIG_OK) {
+	  ret = r;
+	}
       }
     }
 
@@ -970,6 +1028,556 @@ private:
       Setattr(class_methods, Getattr(n, "name"), NewString(""));
     }
 
+    return ret;
+  }
+
+  /* ----------------------------------------------------------------------
+   * struct cgoWrapperInfo
+   *
+   * Information needed by the CGO wrapper functions.
+   * ---------------------------------------------------------------------- */
+
+  struct cgoWrapperInfo {
+    // The function we are generating code for.
+    Node *n;
+    // The name of the Go function.
+    String *go_name;
+    // The overload string for an overloaded function.
+    String *overname;
+    // The name of the C wrapper function.
+    String *wname;
+    // The base classes.
+    List *base;
+    // The parameters.
+    ParmList *parms;
+    // The result type.
+    SwigType *result;
+    // Whether this is a static function, not a class method.
+    bool is_static;
+    // The Go receiver type.
+    String *receiver;
+    // Whether this is a class constructor.
+    bool is_constructor;
+    // Whether this is a class destructor.
+    bool is_destructor;
+  };
+
+  /* ----------------------------------------------------------------------
+   * makeCgoWrappers()
+   *
+   * Write out the wrappers for a function when producing cgo input
+   * files.
+   * ---------------------------------------------------------------------- */
+
+  int makeCgoWrappers(Node *n, String *go_name, String *overname, String *wname, List *base, ParmList *parms, SwigType *result, bool is_static) {
+    Swig_save("makeCgoWrappers", n, "emit:cgotype", "emit:cgotypestruct", NULL);
+
+    cgoWrapperInfo info;
+
+    info.n = n;
+    info.go_name = go_name;
+    info.overname = overname;
+    info.wname = wname;
+    info.base = base;
+    info.parms = parms;
+    info.result = result;
+    info.is_static = is_static;
+
+    info.receiver = class_receiver;
+    if (is_static) {
+      info.receiver = NULL;
+    }
+
+    String *nodetype = Getattr(n, "nodeType");
+    info.is_constructor = Cmp(nodetype, "constructor") == 0;
+    info.is_destructor = Cmp(nodetype, "destructor") == 0;
+    if (info.is_constructor || info.is_destructor) {
+      assert(class_receiver);
+      assert(!base);
+      info.receiver = NULL;
+    }
+
+    int ret = SWIG_OK;
+
+    int r = cgoGoWrapper(&info);
+    if (r != SWIG_OK) {
+      ret = r;
+    }
+
+    r = cgoCommentWrapper(&info);
+    if (r != SWIG_OK) {
+      ret = r;
+    }
+
+    r = cgoGccWrapper(&info);
+    if (r != SWIG_OK) {
+      ret = r;
+    }
+
+    Swig_restore(n);
+
+    return ret;
+  }
+
+  /* ----------------------------------------------------------------------
+   * cgoGoWrapper()
+   *
+   * Write out Go code to call a cgo function.  This code will go into
+   * the generated Go output file.
+   * ---------------------------------------------------------------------- */
+  int cgoGoWrapper(const cgoWrapperInfo *info) {
+
+    Wrapper *dummy = initGoTypemaps(info->parms);
+
+    bool add_to_interface = interfaces && !info->is_constructor && !info->is_destructor && !info->is_static && !info->overname && checkFunctionVisibility(info->n, NULL);
+
+    Printv(f_go_wrappers, "func ", NULL);
+
+    Parm *p = info->parms;
+    int pi = 0;
+
+    // Add the receiver first if this is a method.
+    if (info->receiver) {
+      Printv(f_go_wrappers, "(", NULL);
+      if (info->base && info->receiver) {
+	Printv(f_go_wrappers, "_swig_base", NULL);
+      } else {
+	Printv(f_go_wrappers, Getattr(p, "lname"), NULL);
+	p = nextParm(p);
+	++pi;
+      }
+      Printv(f_go_wrappers, " ", info->receiver, ") ", NULL);
+    }
+
+    Printv(f_go_wrappers, info->go_name, NULL);
+    if (info->overname) {
+      Printv(f_go_wrappers, info->overname, NULL);
+    }
+    Printv(f_go_wrappers, "(", NULL);
+
+    // If we are doing methods, add this method to the interface.
+    if (add_to_interface) {
+      Printv(interfaces, "\t", info->go_name, "(", NULL);
+    }
+
+    // Write out the parameters to both the function definition and
+    // the interface.
+
+    String *parm_print = NewString("");
+
+    int parm_count = emit_num_arguments(info->parms);
+    int required_count = emit_num_required(info->parms);
+    int args = 0;
+
+    for (; pi < parm_count; ++pi) {
+      p = getParm(p);
+      if (pi == 0 && info->is_destructor) {
+	String *cl = exportedName(class_name);
+	Printv(parm_print, Getattr(p, "lname"), " ", cl, NULL);
+	Delete(cl);
+	++args;
+      } else {
+	if (args > 0) {
+	  Printv(parm_print, ", ", NULL);
+	}
+	++args;
+	if (pi >= required_count) {
+	  Printv(parm_print, "_swig_args ...interface{}", NULL);
+	  break;
+	}
+	Printv(parm_print, Getattr(p, "lname"), " ", NULL);
+	String *tm = goType(p, Getattr(p, "type"));
+	Printv(parm_print, tm, NULL);
+	Delete(tm);
+      }
+      p = nextParm(p);
+    }
+
+    Printv(parm_print, ")", NULL);
+
+    // Write out the result type.
+    if (info->is_constructor) {
+      String *cl = exportedName(class_name);
+      Printv(parm_print, " (_swig_ret ", cl, ")", NULL);
+      Delete(cl);
+    } else {
+      if (SwigType_type(info->result) != T_VOID) {
+	String *tm = goType(info->n, info->result);
+	Printv(parm_print, " (_swig_ret ", tm, ")", NULL);
+	Delete(tm);
+      }
+    }
+
+    Printv(f_go_wrappers, parm_print, NULL);
+    if (add_to_interface) {
+      Printv(interfaces, parm_print, "\n", NULL);
+    }
+
+    // Write out the function body.
+
+    Printv(f_go_wrappers, " {\n", NULL);
+
+    if (parm_count > required_count) {
+      Parm *p = info->parms;
+      int i;
+      for (i = 0; i < required_count; ++i) {
+	p = getParm(p);
+	p = nextParm(p);
+      }
+      for (; i < parm_count; ++i) {
+	p = getParm(p);
+	String *tm = goType(p, Getattr(p, "type"));
+	Printv(f_go_wrappers, "\tvar ", Getattr(p, "lname"), " ", tm, "\n", NULL);
+	Printf(f_go_wrappers, "\tif len(_swig_args) > %d {\n", i - required_count);
+	Printf(f_go_wrappers, "\t\t%s = _swig_args[%d].(%s)\n", Getattr(p, "lname"), i - required_count, tm);
+	Printv(f_go_wrappers, "\t}\n", NULL);
+	Delete(tm);
+	p = nextParm(p);
+      }
+    }
+
+    String *call = NewString("\t");
+
+    String *ret_type = NULL;
+    bool memcpy_ret = false;
+    String *wt = NULL;
+    if (SwigType_type(info->result) != T_VOID) {
+      if (info->is_constructor) {
+	ret_type = exportedName(class_name);
+      } else {
+	ret_type = goImType(info->n, info->result);
+      }
+      Printv(f_go_wrappers, "\tvar swig_r ", ret_type, "\n", NULL);
+
+      bool c_struct_type;
+      Delete(cgoTypeForGoValue(info->n, info->result, &c_struct_type));
+      if (c_struct_type) {
+	memcpy_ret = true;
+      }
+
+      if (memcpy_ret) {
+	Printv(call, "swig_r_p := ", NULL);
+      } else {
+	Printv(call, "swig_r = (", ret_type, ")(", NULL);
+      }
+
+      if (info->is_constructor || goTypeIsInterface(info->n, info->result)) {
+	if (info->is_constructor) {
+	  wt = Copy(class_receiver);
+	} else {
+	  wt = goWrapperType(info->n, info->result, true);
+	}
+	Printv(call, wt, "(", NULL);
+      }
+    }
+
+    Printv(call, "C.", info->wname, "(", NULL);
+
+    args = 0;
+
+    if (parm_count > required_count) {
+      Printv(call, "C.swig_intgo(len(_swig_args))", NULL);
+      ++args;
+    }
+
+    if (info->base && info->receiver) {
+      if (args > 0) {
+	Printv(call, ", ", NULL);
+      }
+      ++args;
+      Printv(call, "C.uintptr_t(_swig_base)", NULL);
+    }
+
+    p = info->parms;
+    for (int i = 0; i < parm_count; ++i) {
+      p = getParm(p);
+      if (args > 0) {
+	Printv(call, ", ", NULL);
+      }
+      ++args;
+
+      SwigType *pt = Getattr(p, "type");
+      String *ln = Getattr(p, "lname");
+
+      String *ivar = NewStringf("_swig_i_%d", i);
+
+      String *goin = goGetattr(p, "tmap:goin");
+      if (goin == NULL) {
+	Printv(f_go_wrappers, "\t", ivar, " := ", ln, NULL);
+	if ((i == 0 && info->is_destructor) || ((i > 0 || !info->receiver || info->base || info->is_constructor) && goTypeIsInterface(p, pt))) {
+	  Printv(f_go_wrappers, ".Swigcptr()", NULL);
+	}
+	Printv(f_go_wrappers, "\n", NULL);
+	Setattr(p, "emit:goinput", ln);
+      } else {
+	String *itm = goImType(p, pt);
+	Printv(f_go_wrappers, "\tvar ", ivar, " ", itm, "\n", NULL);
+	goin = Copy(goin);
+	Replaceall(goin, "$input", ln);
+	Replaceall(goin, "$result", ivar);
+	Printv(f_go_wrappers, goin, "\n", NULL);
+	Delete(goin);
+	Setattr(p, "emit:goinput", ivar);
+      }
+
+      bool c_struct_type;
+      String *ct = cgoTypeForGoValue(p, pt, &c_struct_type);
+      if (c_struct_type) {
+	Printv(call, "*(*C.", ct, ")(unsafe.Pointer(&", ivar, "))", NULL);
+      } else {
+	Printv(call, "C.", ct, "(", ivar, ")", NULL);
+      }
+      Delete(ct);
+
+      p = nextParm(p);
+    }
+
+    Printv(f_go_wrappers, call, ")", NULL);
+    Delete(call);
+
+    if (wt) {
+      // Close the type conversion to the wrapper type.
+      Printv(f_go_wrappers, ")", NULL);
+    }
+    if (SwigType_type(info->result) != T_VOID && !memcpy_ret) {
+      // Close the type conversion of the return value.
+      Printv(f_go_wrappers, ")", NULL);
+    }
+
+    Printv(f_go_wrappers, "\n", NULL);
+
+    if (memcpy_ret) {
+      Printv(f_go_wrappers, "\tswig_r = *(*", ret_type, ")(unsafe.Pointer(&swig_r_p))\n", NULL);
+    }
+    if (ret_type) {
+      Delete(ret_type);
+    }
+
+    goargout(info->parms, parm_count);
+
+    if (SwigType_type(info->result) != T_VOID) {
+      String *goout = goTypemapLookup("goout", info->n, "swig_r");
+      if (goout == NULL) {
+	Printv(f_go_wrappers, "\treturn swig_r\n", NULL);
+      } else {
+	String *tm = goType(info->n, info->result);
+	Printv(f_go_wrappers, "\tvar swig_r_1 ", tm, "\n", NULL);
+	goout = Copy(goout);
+	Replaceall(goout, "$input", "swig_r");
+	Replaceall(goout, "$result", "swig_r_1");
+	Printv(f_go_wrappers, goout, "\n", NULL);
+	Printv(f_go_wrappers, "\treturn swig_r_1\n", NULL);
+      }
+    }
+
+    Printv(f_go_wrappers, "}\n\n", NULL);
+
+    DelWrapper(dummy);
+
+    return SWIG_OK;
+  }
+
+  /* ----------------------------------------------------------------------
+   * cgoCommentWrapper()
+   *
+   * Write out a cgo function to call a C/C++ function.  This code
+   * will go into the cgo comment in the generated Go output file.
+   * ---------------------------------------------------------------------- */
+  int cgoCommentWrapper(const cgoWrapperInfo *info) {
+    String *ret_type;
+    if (SwigType_type(info->result) == T_VOID) {
+      ret_type = NewString("void");
+    } else {
+      bool c_struct_type;
+      ret_type = cgoTypeForGoValue(info->n, info->result, &c_struct_type);
+    }
+
+    Printv(f_cgo_comment, "extern ", ret_type, " ", info->wname, "(", NULL);
+
+    Delete(ret_type);
+
+    int parm_count = emit_num_arguments(info->parms);
+    int required_count = emit_num_required(info->parms);
+    int args = 0;
+
+    if (parm_count > required_count) {
+      Printv(f_cgo_comment, "intgo _swig_args", NULL);
+      ++args;
+    }
+
+    if (info->base && info->receiver) {
+      if (args > 0) {
+	Printv(f_cgo_comment, ", ", NULL);
+      }
+      ++args;
+      Printv(f_cgo_comment, "uintptr_t _swig_base", NULL);
+    }
+
+    Parm *p = info->parms;
+    for (int i = 0; i < parm_count; ++i) {
+      p = getParm(p);
+      if (args > 0) {
+	Printv(f_cgo_comment, ", ", NULL);
+      }
+      ++args;
+
+      SwigType *pt = Getattr(p, "type");
+      String *ln = Getattr(p, "lname");
+
+      bool c_struct_type;
+      String *ct = cgoTypeForGoValue(p, pt, &c_struct_type);
+      Printv(f_cgo_comment, ct, " ", ln, NULL);
+      Delete(ct);
+
+      p = nextParm(p);
+    }
+
+    if (args == 0) {
+      Printv(f_cgo_comment, "void", NULL);
+    }
+
+    Printv(f_cgo_comment, ");\n", NULL);
+
+    return SWIG_OK;
+  }
+
+  /* ----------------------------------------------------------------------
+   * cgoGccWrapper()
+   *
+   * Write out code to the C/C++ wrapper file.  This code will be
+   * called by the code generated by cgoCommentWrapper.
+   * ---------------------------------------------------------------------- */
+  int cgoGccWrapper(const cgoWrapperInfo *info) {
+    Wrapper *f = NewWrapper();
+
+    Swig_save("cgoGccWrapper", info->n, "parms", NULL);
+
+    ParmList *parms = info->parms;
+
+    Parm *base_parm = NULL;
+    if (info->base && !isStatic(info->n)) {
+      SwigType *base_type = Copy(getClassType());
+      SwigType_add_pointer(base_type);
+      base_parm = NewParm(base_type, NewString("arg1"), info->n);
+      set_nextSibling(base_parm, parms);
+      parms = base_parm;
+    }
+
+    emit_parameter_variables(parms, f);
+    emit_attach_parmmaps(parms, f);
+    int parm_count = emit_num_arguments(parms);
+    int required_count = emit_num_required(parms);
+
+    emit_return_variable(info->n, info->result, f);
+
+    // Start the function definition.
+
+    String *fnname = NewString("");
+    Printv(fnname, info->wname, "(", NULL);
+
+    int args = 0;
+
+    if (parm_count > required_count) {
+      Printv(fnname, "intgo _swig_optargc", NULL);
+      ++args;
+    }
+
+    Parm *p = parms;
+    for (int i = 0; i < parm_count; ++i) {
+      if (args > 0) {
+	Printv(fnname, ", ", NULL);
+      }
+      ++args;
+
+      p = getParm(p);
+
+      SwigType *pt = Copy(Getattr(p, "type"));
+      if (SwigType_isarray(pt)) {
+	SwigType_del_array(pt);
+	SwigType_add_pointer(pt);
+      }
+      String *pn = NewStringf("_swig_go_%d", i);
+      String *ct = gcCTypeForGoValue(p, pt, pn);
+      Printv(fnname, ct, NULL);
+      Delete(ct);
+      Delete(pn);
+      Delete(pt);
+
+      p = nextParm(p);
+    }
+      
+    Printv(fnname, ")", NULL);
+
+    if (SwigType_type(info->result) == T_VOID) {
+      Printv(f->def, "void ", fnname, NULL);
+    } else {
+      String *ct = gcCTypeForGoValue(info->n, info->result, fnname);
+      Printv(f->def, ct, NULL);
+      Delete(ct);
+
+      String *ln = NewString("_swig_go_result");
+      ct = gcCTypeForGoValue(info->n, info->result, ln);
+      Wrapper_add_local(f, "_swig_go_result", ct);
+      Delete(ct);
+      Delete(ln);
+    }
+
+    Delete(fnname);
+
+    Printv(f->def, " {\n", NULL);
+
+    // Apply the in typemaps.
+
+    p = parms;
+    for (int i = 0; i < parm_count; ++i) {
+      p = getParm(p);
+      String *tm = Getattr(p, "tmap:in");
+      if (!tm) {
+	Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "unable to use type %s as a function argument\n", SwigType_str(Getattr(p, "type"), 0));
+      } else {
+	tm = Copy(tm);
+	String *pn = NewStringf("_swig_go_%d", i);
+	Replaceall(tm, "$input", pn);
+	if (i < required_count) {
+	  Printv(f->code, "\t", tm, "\n", NULL);
+	} else {
+	  Printf(f->code, "\tif (_swig_optargc > %d) {\n", i - required_count);
+	  Printv(f->code, "\t\t", tm, "\n", NULL);
+	  Printv(f->code, "\t}\n", NULL);
+	}
+	Delete(tm);
+	Setattr(p, "emit:input", pn);
+      }
+      p = nextParm(p);
+    }
+
+    Printv(f->code, "\n", NULL);
+
+    // Do the real work of the function.
+
+    checkConstraints(parms, f);
+
+    emitGoAction(info->n, info->base, parms, info->result, f);
+
+    argout(parms, f);
+
+    cleanupFunction(info->n, f, parms);
+
+    if (SwigType_type(info->result) != T_VOID) {
+      Printv(f->code, "\treturn _swig_go_result;\n", NULL);
+    }
+
+    Printv(f->code, "}\n", NULL);
+
+    Wrapper_print(f, f_c_wrappers);
+
+    Swig_restore(info->n);
+
+    DelWrapper(f);
+    if (base_parm) {
+      Delete(base_parm);
+    }
+
     return SWIG_OK;
   }
 
@@ -985,23 +1593,9 @@ private:
    * ---------------------------------------------------------------------- */
 
   int goFunctionWrapper(Node *n, String *name, String *go_name, String *overname, String *wname, List *base, ParmList *parms, SwigType *result, bool is_static) {
-    Wrapper *dummy = NewWrapper();
-    emit_attach_parmmaps(parms, dummy);
+    Wrapper *dummy = initGoTypemaps(parms);
 
-    Parm *p = parms;
     int parm_count = emit_num_arguments(parms);
-    for (int i = 0; i < parm_count; ++i) {
-      p = getParm(p);
-      Swig_cparm_name(p, i);
-      p = nextParm(p);
-    }
-
-    Swig_typemap_attach_parms("default", parms, dummy);
-    Swig_typemap_attach_parms("gotype", parms, dummy);
-    Swig_typemap_attach_parms("goin", parms, dummy);
-    Swig_typemap_attach_parms("goargout", parms, dummy);
-    Swig_typemap_attach_parms("imtype", parms, dummy);
-
     int required_count = emit_num_required(parms);
 
     String *receiver = class_receiver;
@@ -1032,7 +1626,7 @@ private:
     // See whether any of the function parameters are represented by
     // interface values.  When calling the C++ code, we need to convert
     // back to a uintptr.
-    p = parms;
+    Parm *p = parms;
     for (int i = 0; i < parm_count; ++i) {
       p = getParm(p);
       String *ty = Getattr(p, "type");
@@ -1322,11 +1916,11 @@ private:
 	  String *ivar = NewString("");
 	  Printf(ivar, "_swig_i_%d", i);
 	  String *itm = goImType(p, pt);
-	  Printv(f_go_wrappers, "\tvar ", ivar, " ", itm, NULL);
+	  Printv(f_go_wrappers, "\tvar ", ivar, " ", itm, "\n", NULL);
 	  goin = Copy(goin);
 	  Replaceall(goin, "$input", ln);
 	  Replaceall(goin, "$result", ivar);
-	  Printv(f_go_wrappers, goin, NULL);
+	  Printv(f_go_wrappers, goin, "\n", NULL);
 	  Delete(goin);
 	  Printv(call, ivar, NULL);
 	  Setattr(p, "emit:goinput", ivar);
@@ -1391,6 +1985,34 @@ private:
     return SWIG_OK;
   }
 
+  /* ----------------------------------------------------------------------
+   * initGoTypemaps()
+   *
+   * Initialize the typenames for a Go wrapper, returning a dummy
+   * Wrapper*.  Also set consistent names for the parameters.
+   * ---------------------------------------------------------------------- */
+
+  Wrapper* initGoTypemaps(ParmList *parms) {
+    Wrapper *dummy = NewWrapper();
+    emit_attach_parmmaps(parms, dummy);
+
+    Parm *p = parms;
+    int parm_count = emit_num_arguments(parms);
+    for (int i = 0; i < parm_count; ++i) {
+      p = getParm(p);
+      Swig_cparm_name(p, i);
+      p = nextParm(p);
+    }
+
+    Swig_typemap_attach_parms("default", parms, dummy);
+    Swig_typemap_attach_parms("gotype", parms, dummy);
+    Swig_typemap_attach_parms("goin", parms, dummy);
+    Swig_typemap_attach_parms("goargout", parms, dummy);
+    Swig_typemap_attach_parms("imtype", parms, dummy);
+
+    return dummy;
+  }
+
   /* ----------------------------------------------------------------------
    * argName()
    *
@@ -1771,7 +2393,7 @@ private:
    * ----------------------------------------------------------------------- */
 
   void emitGoAction(Node *n, List *base, ParmList *parms, SwigType *result, Wrapper *f) {
-    if (!gccgo_flag && SwigType_type(result) != T_VOID) {
+    if (!gccgo_flag && !cgo_flag && SwigType_type(result) != T_VOID) {
       Wrapper_add_local(f, "swig_stktop", "char *swig_stktop");
       Printv(f->code, "\tswig_stktop = _swig_topofstack();\n", NULL);
     }
@@ -1784,7 +2406,7 @@ private:
       actioncode = NewString("");
 
       String *current = NewString("");
-      if (!gccgo_flag) {
+      if (!gccgo_flag && !cgo_flag) {
 	Printv(current, "swig_a->", NULL);
       }
       Printv(current, Getattr(parms, "lname"), NULL);
@@ -1821,7 +2443,7 @@ private:
       Delete(tm);
     }
 
-    if (!gccgo_flag && SwigType_type(result) != T_VOID) {
+    if (!gccgo_flag && !cgo_flag && SwigType_type(result) != T_VOID) {
       // If the function called back into the Go code, the stack might
       // have been copied.  We need to adjust swig_a accordingly here.
       // This is what cgo does.
@@ -2896,6 +3518,11 @@ private:
       }
     }
 
+    String *fn_with_over_name = Copy(fn_name);
+    if (overname) {
+      Append(fn_with_over_name, overname);
+    }
+
     String *wname = Swig_name_wrapper(fn_name);
 
     if (overname) {
@@ -2935,47 +3562,58 @@ private:
     }
 
     if (!is_ignored) {
-      // Declare the C++ wrapper.
+      if (cgo_flag) {
+	Printv(f_cgo_comment, "extern uintptr_t ", wname, "(int", NULL);
 
-      if (!gccgo_flag) {
-	Printv(f_go_wrappers, "var ", wname, " unsafe.Pointer\n\n", NULL);
+	p = parms;
+	for (int i = 0; i < parm_count; ++i) {
+	  p = getParm(p);
+	  bool c_struct_type;
+	  String *ct = cgoTypeForGoValue(p, Getattr(p, "type"), &c_struct_type);
+	  Printv(f_cgo_comment, ", ", ct, " ", Getattr(p, "lname"), NULL);
+	  p = nextParm(p);
+	}
+	Printv(f_cgo_comment, ");\n", NULL);
       } else {
-	Printv(f_go_wrappers, "//extern ", go_prefix, "_", wname, "\n", NULL);
+	// Declare the C++ wrapper.
+
+	if (!gccgo_flag) {
+	  Printv(f_go_wrappers, "var ", wname, " unsafe.Pointer\n\n", NULL);
+	} else {
+	  Printv(f_go_wrappers, "//extern ", go_prefix, "_", wname, "\n", NULL);
+	}
+
+	Printv(f_go_wrappers, "func ", fn_with_over_name, "(_swig_director int", NULL);
+
+	p = parms;
+	for (int i = 0; i < parm_count; ++i) {
+	  p = getParm(p);
+	  String *tm = goWrapperType(p, Getattr(p, "type"), false);
+	  Printv(f_go_wrappers, ", _ ", tm, NULL);
+	  Delete(tm);
+	  p = nextParm(p);
+	}
+
+	Printv(f_go_wrappers, ") (_swig_ret ", go_type_name, ")", NULL);
+
+	if (!gccgo_flag) {
+	  Printv(f_go_wrappers, " {\n", NULL);
+	  Printv(f_go_wrappers, "\t_swig_p := uintptr(unsafe.Pointer(&_swig_director))\n", NULL);
+	  Printv(f_go_wrappers, "\t_cgo_runtime_cgocall(", wname, ", _swig_p)\n", NULL);
+	  Printv(f_go_wrappers, "\treturn\n", NULL);
+	  Printv(f_go_wrappers, "}", NULL);
+	}
+
+	Printv(f_go_wrappers, "\n\n", NULL);
       }
 
-      Printv(f_go_wrappers, "func ", fn_name, NULL);
-      if (overname) {
-	Printv(f_go_wrappers, overname, NULL);
-      }
-      Printv(f_go_wrappers, "(_swig_director int", NULL);
-
-      p = parms;
-      for (int i = 0; i < parm_count; ++i) {
-	p = getParm(p);
-	String *tm = goType(p, Getattr(p, "type"));
-	Printv(f_go_wrappers, ", _ ", tm, NULL);
-	Delete(tm);
-	p = nextParm(p);
-      }
-
-      Printv(f_go_wrappers, ") (_swig_ret ", go_type_name, ")", NULL);
-
-      if (!gccgo_flag) {
-	Printv(f_go_wrappers, " {\n", NULL);
-	Printv(f_go_wrappers, "\t_swig_p := uintptr(unsafe.Pointer(&_swig_director))\n", NULL);
-	Printv(f_go_wrappers, "\t_cgo_runtime_cgocall(", wname, ", _swig_p)\n", NULL);
-	Printv(f_go_wrappers, "\treturn\n", NULL);
-	Printv(f_go_wrappers, "}", NULL);
-      }
-
-      Printv(f_go_wrappers, "\n\n", NULL);
+      // Write out the Go function that calls the wrapper.
 
       Printv(f_go_wrappers, "func ", func_with_over_name, "(v interface{}", NULL);
 
       p = parms;
       for (int i = 0; i < parm_count; ++i) {
 	p = getParm(p);
-	// Set the lname parameter.
 	Printv(f_go_wrappers, ", ", Getattr(p, "lname"), " ", NULL);
 	String *tm = goType(p, Getattr(p, "type"));
 	Printv(f_go_wrappers, tm, NULL);
@@ -2987,25 +3625,71 @@ private:
 
       Printv(f_go_wrappers, "\tp := &", director_struct_name, "{0, v}\n", NULL);
 
-      if (gccgo_flag) {
+      if (gccgo_flag && !cgo_flag) {
 	Printv(f_go_wrappers, "\tdefer SwigCgocallDone()\n", NULL);
 	Printv(f_go_wrappers, "\tSwigCgocall()\n", NULL);
       }
 
-      Printv(f_go_wrappers, "\tp.", class_receiver, " = ", fn_name, NULL);
-      if (overname) {
-	Printv(f_go_wrappers, overname, NULL);
+      String *call = NewString("");
+
+      Printv(call, "\tp.", class_receiver, " = ", NULL);
+      if (cgo_flag) {
+	Printv(call, go_type_name, "(C.", wname, "(C.int(swigDirectorAdd(p))", NULL);
+      } else {
+	Printv(call, fn_with_over_name, "(swigDirectorAdd(p)", NULL);
       }
-      Printv(f_go_wrappers, "(swigDirectorAdd(p)", NULL);
 
       p = parms;
       for (int i = 0; i < parm_count; ++i) {
+	Printv(call, ", ", NULL);
+
 	p = getParm(p);
-	Printv(f_go_wrappers, ", ", Getattr(p, "lname"), NULL);
+	String *pt = Getattr(p, "type");
+	String *ln = Getattr(p, "lname");
+
+	String *ivar = NewStringf("_swig_i_%d", i);
+
+	String *goin = goGetattr(p, "tmap:goin");
+	if (goin == NULL) {
+	  Printv(f_go_wrappers, "\t", ivar, " := ", ln, NULL);
+	  if (goTypeIsInterface(p, pt)) {
+	    Printv(f_go_wrappers, ".Swigcptr()", NULL);
+	  }
+	  Printv(f_go_wrappers, "\n", NULL);
+	} else {
+	  String *itm = goImType(p, pt);
+	  Printv(f_go_wrappers, "\tvar ", ivar, " ", itm, "\n", NULL);
+	  goin = Copy(goin);
+	  Replaceall(goin, "$input", ln);
+	  Replaceall(goin, "$result", ivar);
+	  Printv(f_go_wrappers, goin, "\n", NULL);
+	  Delete(goin);
+	}
+
+	Setattr(p, "emit:goinput", ivar);
+
+	if (cgo_flag) {
+	  bool c_struct_type;
+	  String *ct = cgoTypeForGoValue(p, pt, &c_struct_type);
+	  if (c_struct_type) {
+	    Printv(call, "*(*C.", ct, ")(unsafe.Pointer(&", ivar, "))", NULL);
+	  } else {
+	    Printv(call, "C.", ct, "(", ivar, ")", NULL);
+	  }
+	  Delete(ct);
+	} else {
+	  Printv(call, ivar, NULL);
+	}
 	p = nextParm(p);
       }
 
-      Printv(f_go_wrappers, ")\n", NULL);
+      Printv(call, ")", NULL);
+      if (cgo_flag) {
+	Printv(call, ")", NULL);
+      }
+
+      Printv(f_go_wrappers, call, "\n", NULL);
+
       Printv(f_go_wrappers, "\treturn p\n", NULL);
       Printv(f_go_wrappers, "}\n\n", NULL);
 
@@ -3038,7 +3722,26 @@ private:
       Printv(action, ");", NULL);
       Setattr(n, "wrap:action", action);
 
-      if (!gccgo_flag) {
+      if (cgo_flag) {
+	cgoWrapperInfo info;
+
+	info.n = n;
+	info.go_name = func_name;
+	info.overname = overname;
+	info.wname = wname;
+	info.base = NULL;
+	info.parms = first_parm;
+	info.result = result;
+	info.is_static = false;
+	info.receiver = NULL;
+	info.is_constructor = true;
+	info.is_destructor = false;
+
+	int r = cgoGccWrapper(&info);
+	if (r != SWIG_OK) {
+	  return r;
+	}
+      } else if (!gccgo_flag) {
 	int r = gcFunctionWrapper(wname);
 	if (r != SWIG_OK) {
 	  return r;
@@ -3101,6 +3804,7 @@ private:
     Delete(go_type_name);
     Delete(director_struct_name);
     Delete(fn_name);
+    Delete(fn_with_over_name);
     Delete(func_name);
     Delete(func_with_over_name);
     Delete(wname);
@@ -3184,18 +3888,9 @@ private:
     Printv(director_sig, "{\n", NULL);
 
     if (!is_ignored) {
-      makeDirectorDestructorWrapper(go_name, director_sig);
+      makeDirectorDestructorWrapper(go_name, director_struct_name, director_sig);
 
       Printv(f_c_directors, "  delete swig_mem;\n", NULL);
-
-      Printv(f_go_wrappers, "func ", go_name, "(c int) {\n", NULL);
-      if (gccgo_flag) {
-	Printv(f_go_wrappers, "\tSwigCgocallBack()\n", NULL);
-	Printv(f_go_wrappers, "\tdefer SwigCgocallBackDone()\n", NULL);
-      }
-      Printv(f_go_wrappers, "\tswigDirectorLookup(c).(*", director_struct_name, ").", class_receiver, " = 0\n", NULL);
-      Printv(f_go_wrappers, "\tswigDirectorDelete(c)\n", NULL);
-      Printv(f_go_wrappers, "}\n\n", NULL);
     }
 
     Printv(f_c_directors, "}\n\n", NULL);
@@ -3216,7 +3911,21 @@ private:
    * unfinished.
    * ------------------------------------------------------------ */
 
-  void makeDirectorDestructorWrapper(String *go_name, String *director_sig) {
+  void makeDirectorDestructorWrapper(String *go_name, String *director_struct_name, String *director_sig) {
+    if (cgo_flag) {
+      makeCgoDirectorDestructorWrapper(go_name, director_struct_name, director_sig);
+      return;
+    }
+
+    Printv(f_go_wrappers, "func ", go_name, "(c int) {\n", NULL);
+    if (gccgo_flag) {
+      Printv(f_go_wrappers, "\tSwigCgocallBack()\n", NULL);
+      Printv(f_go_wrappers, "\tdefer SwigCgocallBackDone()\n", NULL);
+    }
+    Printv(f_go_wrappers, "\tswigDirectorLookup(c).(*", director_struct_name, ").", class_receiver, " = 0\n", NULL);
+    Printv(f_go_wrappers, "\tswigDirectorDelete(c)\n", NULL);
+    Printv(f_go_wrappers, "}\n\n", NULL);
+
     String *wname = NewString("_swiggo_wrap_DeleteDirector_");
     Append(wname, class_name);
 
@@ -3249,6 +3958,28 @@ private:
     Delete(wname);
   }
 
+  /* ------------------------------------------------------------
+   * makeCgoDirectorDestructorWrapper
+   *
+   * When using cgo, emit the function wrapper for the destructor of a
+   * director class.
+   * ------------------------------------------------------------ */
+
+  void makeCgoDirectorDestructorWrapper(String *go_name, String *director_struct_name, String *director_sig) {
+    String *wname = Copy(go_name);
+    Append(wname, unique_id);
+
+    Printv(f_go_wrappers, "//export ", wname, "\n", NULL);
+    Printv(f_go_wrappers, "func ", wname, "(c int) {\n", NULL);
+    Printv(f_go_wrappers, "\tswigDirectorLookup(c).(*", director_struct_name, ").", class_receiver, " = 0\n", NULL);
+    Printv(f_go_wrappers, "\tswigDirectorDelete(c)\n", NULL);
+    Printv(f_go_wrappers, "}\n\n", NULL);
+
+    Printv(f_c_directors, "extern \"C\" void ", wname, "(intgo);\n", NULL);
+    Printv(f_c_directors, director_sig, NULL);
+    Printv(f_c_directors, "  ", wname, "(go_val);\n", NULL);
+  }
+
   /* ------------------------------------------------------------
    * classDirectorMethod
    *
@@ -3404,6 +4135,9 @@ private:
     if (overname) {
       Append(callback_name, overname);
     }
+    if (cgo_flag) {
+      Append(callback_name, unique_id);
+    }
 
     String *upcall_name = Copy(director_struct_name);
     Append(upcall_name, "_upcall_");
@@ -3462,43 +4196,68 @@ private:
       Printv(f_go_wrappers, "}\n\n", NULL);
 
       if (!GetFlag(n, "abstract")) {
-	// Declare the upcall function, which calls the method on the
-	// parent class.
+	if (cgo_flag) {
+	  Printv(f_cgo_comment, "extern ", NULL);
 
-	if (!gccgo_flag) {
-	  Printv(f_go_wrappers, "var ", upcall_wname, " unsafe.Pointer\n\n", NULL);
+	  if (SwigType_type(result) == T_VOID) {
+	    Printv(f_cgo_comment, "void", NULL);
+	  } else {
+	    bool c_struct_type;
+	    String *ret_type = cgoTypeForGoValue(n, result, &c_struct_type);
+	    Printv(f_cgo_comment, ret_type, NULL);
+	    Delete(ret_type);
+	  }
+
+	  Printv(f_cgo_comment, " ", upcall_wname, "(uintptr_t", NULL);
+
+	  p = parms;
+	  for (int i = 0; i < parm_count; ++i) {
+	    p = getParm(p);
+	    bool c_struct_type;
+	    String *ct = cgoTypeForGoValue(p, Getattr(p, "type"), &c_struct_type);
+	    Printv(f_cgo_comment, ", ", ct, " ", Getattr(p, "lname"), NULL);
+	    p = nextParm(p);
+	  }
+	  Printv(f_cgo_comment, ");\n", NULL);
 	} else {
-	  Printv(f_go_wrappers, "//extern ", go_prefix, "_", upcall_wname, "\n", NULL);
+	  // Declare the upcall function, which calls the method on
+	  // the parent class.
+
+	  if (!gccgo_flag) {
+	    Printv(f_go_wrappers, "var ", upcall_wname, " unsafe.Pointer\n\n", NULL);
+	  } else {
+	    Printv(f_go_wrappers, "//extern ", go_prefix, "_", upcall_wname, "\n", NULL);
+	  }
+
+	  Printv(f_go_wrappers, "func ", upcall_gc_name, "(_swig_ptr ", go_type_name, NULL);
+
+	  p = parms;
+	  for (int i = 0; i < parm_count; ++i) {
+	    p = getParm(p);
+	    String *tm = goWrapperType(p, Getattr(p, "type"), false);
+	    Printv(f_go_wrappers, ", _ ", tm, NULL);
+	    Delete(tm);
+	    p = nextParm(p);
+	  }
+
+	  Printv(f_go_wrappers, ")", NULL);
+
+	  if (SwigType_type(result) != T_VOID) {
+	    String *tm = goWrapperType(n, result, true);
+	    Printv(f_go_wrappers, " (_swig_ret ", tm, ")", NULL);
+	    Delete(tm);
+	  }
+
+	  if (!gccgo_flag) {
+	    Printv(f_go_wrappers, " {\n", NULL);
+	    Printv(f_go_wrappers, "\t_swig_p := uintptr(unsafe.Pointer(&_swig_ptr))\n", NULL);
+	    Printv(f_go_wrappers, "\t_cgo_runtime_cgocall(", upcall_wname, ", _swig_p)\n", NULL);
+	    Printv(f_go_wrappers, "\treturn\n", NULL);
+	    Printv(f_go_wrappers, "}", NULL);
+	  }
+
+	  Printv(f_go_wrappers, "\n\n", NULL);
 	}
-
-	Printv(f_go_wrappers, "func ", upcall_gc_name, "(_swig_ptr ", go_type_name, NULL);
-
-	p = parms;
-	for (int i = 0; i < parm_count; ++i) {
-	  p = getParm(p);
-	  String *tm = goWrapperType(p, Getattr(p, "type"), false);
-	  Printv(f_go_wrappers, ", _ ", tm, NULL);
-	  Delete(tm);
-	  p = nextParm(p);
-	}
-
-	Printv(f_go_wrappers, ")", NULL);
-
-	if (SwigType_type(result) != T_VOID) {
-	  String *tm = goWrapperType(n, result, true);
-	  Printv(f_go_wrappers, " (_swig_ret ", tm, ")", NULL);
-	  Delete(tm);
-	}
-
-	if (!gccgo_flag) {
-	  Printv(f_go_wrappers, " {\n", NULL);
-	  Printv(f_go_wrappers, "\t_swig_p := uintptr(unsafe.Pointer(&_swig_ptr))\n", NULL);
-	  Printv(f_go_wrappers, "\t_cgo_runtime_cgocall(", upcall_wname, ", _swig_p)\n", NULL);
-	  Printv(f_go_wrappers, "\treturn\n", NULL);
-	  Printv(f_go_wrappers, "}", NULL);
-	}
-
-	Printv(f_go_wrappers, "\n\n", NULL);
       }
 
       // Define the method on the director class in Go.
@@ -3554,14 +4313,26 @@ private:
       if (GetFlag(n, "abstract")) {
 	Printv(f_go_wrappers, "\tpanic(\"call to pure virtual method\")\n", NULL);
       } else {
+	String *ret_type = NULL;
+	bool memcpy_ret = false;
+	String *wt = NULL;
 	bool has_goout = false;
 	String *goout = NULL;
 	if (SwigType_type(result) != T_VOID) {
-	  Printv(f_go_wrappers, "\tvar swig_r ", goImType(n, result), "\n", NULL);
+	  ret_type = goImType(n, result);
+	  Printv(f_go_wrappers, "\tvar swig_r ", ret_type, "\n", NULL);
 	  goout = goTypemapLookup("goout", n, "swig_r");
 	  if (goout) {
 	    has_goout = true;
 	  }
+
+	  if (cgo_flag) {
+	    bool c_struct_type;
+	    Delete(cgoTypeForGoValue(n, result, &c_struct_type));
+	    if (c_struct_type) {
+	      memcpy_ret = true;
+	    }
+	  }
 	}
 
 	p = parms;
@@ -3575,7 +4346,7 @@ private:
 
 	String *call = NewString("");
 
-	if (gccgo_flag) {
+	if (gccgo_flag && !cgo_flag) {
 	  if (has_goout) {
 	    Printv(call, "\tfunc() {\n", NULL);
 	  }
@@ -3585,9 +4356,33 @@ private:
 
 	Printv(call, "\t", NULL);
 	if (SwigType_type(result) != T_VOID) {
-	  Printv(call, "swig_r = ", NULL);
+	  if (memcpy_ret) {
+	    Printv(call, "swig_r_p := ", NULL);
+	  } else {
+	    Printv(call, "swig_r = ", NULL);
+	    if (cgo_flag) {
+	      Printv(call, "(", ret_type, ")(", NULL);
+	    }
+	  }
+	  if (cgo_flag && goTypeIsInterface(n, result)) {
+	    wt = goWrapperType(n, result, true);
+	    Printv(call, "(", wt, ")(", NULL);
+	  }
+	}
+
+	if (cgo_flag) {
+	  Printv(call, "C.", upcall_wname, NULL);
+	} else {
+	  Printv(call, upcall_gc_name, NULL);
+	}
+	Printv(call, "(", NULL);
+	if (cgo_flag) {
+	  Printv(call, "C.uintptr_t(", NULL);
+	}
+	Printv(call, "swig_p.", go_type_name, NULL);
+	if (cgo_flag) {
+	  Printv(call, ")", NULL);
 	}
-	Printv(call, upcall_gc_name, "(swig_p.", go_type_name, NULL);
 
 	p = parms;
 	for (int i = 0; i < parm_count; ++i) {
@@ -3597,41 +4392,70 @@ private:
 
 	  String *ln = Getattr(p, "lname");
 
+	  String *ivar = NewStringf("_swig_i_%d", i);
+
 	  // This is an ordinary call from Go to C++, so adjust using
 	  // the goin typemap.
 	  String *goin = goGetattr(p, "tmap:goin");
 	  if (goin == NULL) {
-	    Printv(call, ln, NULL);
+	    Printv(f_go_wrappers, "\t", ivar, " := ", ln, NULL);
 	    if (goTypeIsInterface(p, pt)) {
-	      Printv(call, ".Swigcptr()", NULL);
+	      Printv(f_go_wrappers, ".Swigcptr()", NULL);
 	    }
-	    Setattr(p, "emit:goinput", ln);
+	    Printv(f_go_wrappers, "\n", NULL);
 	  } else {
-	    String *ivar = NewString("");
-	    Printf(ivar, "_swig_i_%d", i);
 	    String *itm = goImType(p, pt);
-	    Printv(f_go_wrappers, "\tvar ", ivar, " ", itm, NULL);
+	    Printv(f_go_wrappers, "\tvar ", ivar, " ", itm, "\n", NULL);
 	    goin = Copy(goin);
 	    Replaceall(goin, "$input", ln);
 	    Replaceall(goin, "$result", ivar);
 	    Printv(f_go_wrappers, goin, NULL);
 	    Delete(goin);
+	  }
+
+	  Setattr(p, "emit:goinput", ivar);
+
+	  if (cgo_flag) {
+	    bool c_struct_type;
+	    String *ct = cgoTypeForGoValue(p, pt, &c_struct_type);
+	    if (c_struct_type) {
+	      Printv(call, "*(*C.", ct, ")(unsafe.Pointer(&", ivar, "))", NULL);
+	    } else {
+	      Printv(call, "C.", ct, "(", ivar, ")", NULL);
+	    }
+	  } else {
 	    Printv(call, ivar, NULL);
-	    Setattr(p, "emit:goinput", ivar);
 	  }
 
 	  p = nextParm(p);
 	}
 
-	Printv(call, ")\n", NULL);
+	Printv(call, ")", NULL);
 
-	if (gccgo_flag && has_goout) {
-	  Printv(call, "\t}()\n", NULL);
+	if (gccgo_flag && !cgo_flag && has_goout) {
+	  Printv(call, "\n\t}()", NULL);
 	}
 
+	if (cgo_flag) {
+	  if (wt) {
+	    // Close the type conversion to the wrapper type.
+	    Printv(call, ")", NULL);
+	  }
+	  if (SwigType_type(result) != T_VOID && !memcpy_ret) {
+	    // Close the type conversion of the return value.
+	    Printv(call, ")", NULL);
+	  }
+	}
+
+	Printv(call, "\n", NULL);
+
 	Printv(f_go_wrappers, call, NULL);
 	Delete(call);
 
+	if (memcpy_ret) {
+	  Printv(f_go_wrappers, "\tswig_r = *(*", ret_type, ")(unsafe.Pointer(&swig_r_p))\n", NULL);
+	}
+
 	goargout(parms, parm_count);
 
 	if (SwigType_type(result) != T_VOID) {
@@ -3646,6 +4470,13 @@ private:
 	    Printv(f_go_wrappers, "\treturn swig_r_1\n", NULL);
 	  }
 	}
+
+	if (ret_type) {
+	  Delete(ret_type);
+	}
+	if (wt) {
+	  Delete(wt);
+	}
       }
 
       Printv(f_go_wrappers, "}\n\n", NULL);
@@ -3727,7 +4558,26 @@ private:
 	Printv(action, ");", NULL);
 	Setattr(n, "wrap:action", action);
 
-	if (!gccgo_flag) {
+	if (cgo_flag) {
+	  cgoWrapperInfo info;
+
+	  info.n = n;
+	  info.go_name = go_name;
+	  info.overname = overname;
+	  info.wname = upcall_wname;
+	  info.base = NULL;
+	  info.parms = first_parm;
+	  info.result = result;
+	  info.is_static = is_static;
+	  info.receiver = NULL;
+	  info.is_constructor = false;
+	  info.is_destructor = false;
+
+	  int r = cgoGccWrapper(&info);
+	  if (r != SWIG_OK) {
+	    return r;
+	  }
+	} else if (!gccgo_flag) {
 	  // Write the upcall wrapper function.  This is compiled by gc
 	  // and calls the C++ function.
 	  int r = gcFunctionWrapper(upcall_wname);
@@ -3778,15 +4628,27 @@ private:
 
 	Printv(f_go_wrappers, " {\n", NULL);
 
+	String *ret_type = NULL;
+	bool memcpy_ret = false;
+	String *wt = NULL;
 	String *goout = NULL;
 	if (SwigType_type(result) != T_VOID) {
-	  Printv(f_go_wrappers, "\tvar swig_r ", goImType(n, result), "\n", NULL);
+	  ret_type = goImType(n, result);
+	  Printv(f_go_wrappers, "\tvar swig_r ", ret_type, "\n", NULL);
 	  goout = goTypemapLookup("goout", n, "swig_r");
+
+	  if (cgo_flag) {
+	    bool c_struct_type;
+	    Delete(cgoTypeForGoValue(n, result, &c_struct_type));
+	    if (c_struct_type) {
+	      memcpy_ret = true;
+	    }
+	  }
 	}
 
 	String *call = NewString("");
 
-	if (gccgo_flag) {
+	if (gccgo_flag && !cgo_flag) {
 	  if (goout != NULL) {
 	    Printv(call, "\tfunc() {\n", NULL);
 	  }
@@ -3796,9 +4658,33 @@ private:
 
 	Printv(call, "\t", NULL);
 	if (SwigType_type(result) != T_VOID) {
-	  Printv(call, "swig_r = ", NULL);
+	  if (memcpy_ret) {
+	    Printv(call, "swig_r_p := ", NULL);
+	  } else {
+	    Printv(call, "swig_r = ", NULL);
+	    if (cgo_flag) {
+	      Printv(call, "(", ret_type, ")(", NULL);
+	    }
+	  }
+	  if (cgo_flag && goTypeIsInterface(n, result)) {
+	    wt = goWrapperType(n, result, true);
+	    Printv(call, "(", wt, ")(", NULL);
+	  }
+	}
+
+	if (cgo_flag) {
+	  Printv(call, "C.", upcall_wname, NULL);
+	} else {
+	  Printv(call, upcall_gc_name, NULL);
+	}
+	Printv(call, "(", NULL);
+	if (cgo_flag) {
+	  Printv(call, "C.uintptr_t(", NULL);
+	}
+	Printv(call, "p.(*", director_struct_name, ").", go_type_name, NULL);
+	if (cgo_flag) {
+	  Printv(call, ")", NULL);
 	}
-	Printv(call, upcall_gc_name, "(p.(*", director_struct_name, ").", go_type_name, NULL);
 
 	p = parms;
 	for (int i = 0; i < parm_count; ++i) {
@@ -3806,27 +4692,39 @@ private:
 	  p = getParm(p);
 	  SwigType *pt = Getattr(p, "type");
 
+	  String *ivar = NewStringf("_swig_i_%d", i);
+
 	  String *ln = Copy(Getattr(p, "lname"));
-	  if (goTypeIsInterface(p, pt)) {
-	    Printv(ln, ".Swigcptr()", NULL);
-	  }
 
 	  String *goin = goGetattr(p, "tmap:goin");
 	  if (goin == NULL) {
-	    Printv(call, ln, NULL);
-	    Setattr(p, "emit:goinput", ln);
+	    Printv(f_go_wrappers, "\t", ivar, " := ", ln, NULL);
+	    if (goTypeIsInterface(p, pt)) {
+	      Printv(f_go_wrappers, ".Swigcptr()", NULL);
+	    }
+	    Printv(f_go_wrappers, "\n", NULL);
 	  } else {
-	    String *ivar = NewString("");
-	    Printf(ivar, "_swig_i_%d", i);
 	    String *itm = goImType(p, pt);
-	    Printv(f_go_wrappers, "\tvar ", ivar, " ", itm, NULL);
+	    Printv(f_go_wrappers, "\tvar ", ivar, " ", itm, "\n", NULL);
 	    goin = Copy(goin);
 	    Replaceall(goin, "$input", ln);
 	    Replaceall(goin, "$result", ivar);
 	    Printv(f_go_wrappers, goin, NULL);
 	    Delete(goin);
+	  }
+
+	  Setattr(p, "emit:goinput", ivar);
+
+	  if (cgo_flag) {
+	    bool c_struct_type;
+	    String *ct = cgoTypeForGoValue(p, pt, &c_struct_type);
+	    if (c_struct_type) {
+	      Printv(call, "*(*C.", ct, ")(unsafe.Pointer(&", ivar, "))", NULL);
+	    } else {
+	      Printv(call, "C.", ct, "(", ivar, ")", NULL);
+	    }
+	  } else {
 	    Printv(call, ivar, NULL);
-	    Setattr(p, "emit:goinput", ivar);
 	  }
 
 	  Delete(ln);
@@ -3834,15 +4732,32 @@ private:
 	  p = nextParm(p);
 	}
 
-	Printv(call, ")\n", NULL);
+	Printv(call, ")", NULL);
 
-	if (gccgo_flag && goout != NULL) {
-	  Printv(call, "\t}()\n", NULL);
+	if (gccgo_flag && !cgo_flag && goout != NULL) {
+	  Printv(call, "\n\t}()", NULL);
 	}
 
+	if (cgo_flag) {
+	  if (wt) {
+	    // Close the type conversion to the wrapper type.
+	    Printv(call, ")", NULL);
+	  }
+	  if (SwigType_type(result) != T_VOID && !memcpy_ret) {
+	    // Close the type conversion of the return value.
+	    Printv(call, ")", NULL);
+	  }
+	}
+
+	Printv(call, "\n", NULL);
+
 	Printv(f_go_wrappers, call, NULL);
 	Delete(call);
 
+	if (memcpy_ret) {
+	  Printv(f_go_wrappers, "\tswig_r = *(*", ret_type, ")(unsafe.Pointer(&swig_r_p))\n", NULL);
+	}
+
 	goargout(parms, parm_count);
 
 	if (SwigType_type(result) != T_VOID) {
@@ -3859,11 +4774,22 @@ private:
 	}
 
 	Printv(f_go_wrappers, "}\n\n", NULL);
+
+	if (ret_type) {
+	  Delete(ret_type);
+	}
+	if (wt) {
+	  Delete(wt);
+	}
       }
 
       // The Go function which invokes the method.  This is called
       // from by the C++ method on the director class.
 
+      if (cgo_flag) {
+	Printv(f_go_wrappers, "//export ", callback_name, "\n", NULL);
+      }
+
       Printv(f_go_wrappers, "func ", callback_name, "(swig_c int", NULL);
 
       p = parms;
@@ -3970,7 +4896,7 @@ private:
 	}
 	Printv(call, "\n", NULL);
 
-	if (gccgo_flag) {
+	if (gccgo_flag && !cgo_flag) {
 	  if (goout != NULL) {
 	    Printv(f_go_wrappers, "\tfunc() {\n", NULL);
 	  }
@@ -3983,7 +4909,7 @@ private:
 	Printv(f_go_wrappers, call, NULL);
 	Delete(call);
 
-	if (gccgo_flag && goout != NULL) {
+	if (gccgo_flag && !cgo_flag && goout != NULL) {
 	  Printv(f_go_wrappers, "\t}()\n", NULL);
 	}
 
@@ -4062,6 +4988,7 @@ private:
     Delete(go_type_name);
     Delete(director_struct_name);
     Delete(interface_name);
+    Delete(callback_name);
     Delete(upcall_name);
     Delete(go_name);
     DelWrapper(w);
@@ -4075,6 +5002,11 @@ private:
    * Emit the function wrapper for a director method.
    * ------------------------------------------------------------ */
   void makeDirectorMethodWrapper(Node *n, Wrapper *w, String *callback_name) {
+    if (cgo_flag) {
+      makeCgoDirectorMethodWrapper(n, w, callback_name);
+      return;
+    }
+
     ParmList *parms = Getattr(n, "wrap:parms");
     SwigType *result = Getattr(n, "type");
 
@@ -4298,6 +5230,129 @@ private:
     Delete(callback_wname);
   }
 
+  /* ------------------------------------------------------------
+   * makeDirectorMethodWrapper
+   *
+   * Emit the function wrapper for a director method for cgo.
+   * ------------------------------------------------------------ */
+
+  void makeCgoDirectorMethodWrapper(Node *n, Wrapper *w, String *callback_name) {
+    ParmList *parms = Getattr(n, "wrap:parms");
+    SwigType *result = Getattr(n, "type");
+
+    Printv(f_c_directors, "extern \"C\" ", NULL);
+
+    String *fnname = Copy(callback_name);
+    Append(fnname, "(int");
+
+    Parm *p = parms;
+    while (p) {
+      while (checkAttribute(p, "tmap:directorin:numinputs", "0")) {
+	p = Getattr(p, "tmap:directorin:next");
+      }
+      String *cg = gcCTypeForGoValue(p, Getattr(p, "type"), Getattr(p, "lname"));
+      Printv(fnname, ", ", cg, NULL);
+      Delete(cg);
+      p = Getattr(p, "tmap:directorin:next");
+    }
+
+    Printv(fnname, ")", NULL);
+
+    if (SwigType_type(result) == T_VOID) {
+      Printv(f_c_directors, "void ", fnname, NULL);
+    } else {
+      String *tm = gcCTypeForGoValue(n, result, fnname);
+      Printv(f_c_directors, tm, NULL);
+      Delete(tm);
+    }
+
+    Delete(fnname);
+
+    Printv(f_c_directors, ";\n", NULL);
+
+    if (SwigType_type(result) != T_VOID) {
+      String *r = NewString(Swig_cresult_name());
+      String *tm = gcCTypeForGoValue(n, result, r);
+      Wrapper_add_local(w, r, tm);
+      Delete(tm);
+      Delete(r);
+    }
+
+    String *args = NewString("");
+
+    p = parms;
+    while (p) {
+      while (checkAttribute(p, "tmap:directorin:numinputs", "0")) {
+	p = Getattr(p, "tmap:directorin:next");
+      }
+
+      String *pn = NewString("swig_");
+      Append(pn, Getattr(p, "lname"));
+      Setattr(p, "emit:directorinput", pn);
+
+      String *tm = gcCTypeForGoValue(p, Getattr(p, "type"), pn);
+      Wrapper_add_local(w, pn, tm);
+      Delete(tm);
+
+      tm = Getattr(p, "tmap:directorin");
+      if (!tm) {
+	Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file,
+		     line_number, "Unable to use type %s as director method argument\n", SwigType_str(Getattr(p, "type"), 0));
+      } else {
+	tm = Copy(tm);
+	Replaceall(tm, "$input", pn);
+	Replaceall(tm, "$owner", 0);
+	Printv(w->code, "  ", tm, "\n", NULL);
+	Delete(tm);
+
+	Printv(args, ", ", pn, NULL);
+      }
+
+      p = Getattr(p, "tmap:directorin:next");
+    }
+
+    Printv(w->code, "  ", NULL);
+    if (SwigType_type(result) != T_VOID) {
+      Printv(w->code, Swig_cresult_name(), " = ", NULL);
+    }
+    Printv(w->code, callback_name, "(go_val", args, ");\n", NULL);
+
+    /* Marshal outputs */
+    for (p = parms; p; ) {
+      String *tm;
+      if ((tm = Getattr(p, "tmap:directorargout"))) {
+	tm = Copy(tm);
+	Replaceall(tm, "$result", "jresult");
+	Replaceall(tm, "$input", Getattr(p, "emit:directorinput"));
+	Printv(w->code, tm, "\n", NULL);
+	Delete(tm);
+	p = Getattr(p, "tmap:directorargout:next");
+      } else {
+	p = nextSibling(p);
+      }
+    }
+
+    if (SwigType_type(result) != T_VOID) {
+      String *result_str = NewString("c_result");
+      String *tm = Swig_typemap_lookup("directorout", n, result_str, NULL);
+      if (!tm) {
+	Swig_warning(WARN_TYPEMAP_DIRECTOROUT_UNDEF, input_file, line_number,
+		     "Unable to use type %s as director method result\n", SwigType_str(result, 0));
+      } else {
+	tm = Copy(tm);
+	Replaceall(tm, "$input", Swig_cresult_name());
+	Replaceall(tm, "$result", "c_result");
+	Printv(w->code, "  ", tm, "\n", NULL);
+	String *retstr = SwigType_rcaststr(result, "c_result");
+	Printv(w->code, "  return ", retstr, ";\n", NULL);
+	Delete(retstr);
+	Delete(tm);
+      }
+      Delete(result_str);
+    }
+  }
+
+
   /* ------------------------------------------------------------
    * classDirectorEnd
    *
@@ -5218,6 +6273,106 @@ private:
     return ret;
   }
 
+  /* ----------------------------------------------------------------------
+   * cgoTypeForGoValue()
+   *
+   * Given a SWIG type, return a string for the C type to use for the
+   * cgo wrapper code.  This always returns a simple identifier, since
+   * it is used in Go code as C.name.
+   *
+   * This sets *c_struct_type if the C type uses a struct where the Go
+   * type uses a simple type.  This is true for strings and slices.
+   * When this is true the Go code has to jump through unsafe hoops to
+   * pass the type checker.
+   * ---------------------------------------------------------------------- */
+
+  String *cgoTypeForGoValue(Node *n, SwigType *type, bool *c_struct_type) {
+    *c_struct_type = false;
+
+    bool is_interface;
+    String *go_type = goTypeWithInfo(n, type, false, &is_interface);
+    if (is_interface) {
+      Delete(go_type);
+      return NewString("uintptr_t");
+    }
+    if (Strcmp(go_type, "uintptr") == 0) {
+      Delete(go_type);
+      return NewString("uintptr_t");
+    }
+    if (((char*)Char(go_type))[0] == '*') {
+      // Treat all pointers as void*.  There is no meaningful type
+      // checking going on here anyhow, and that lets us avoid
+      // worrying about defining the base type of the pointer.
+      Delete(go_type);
+      return NewString("swig_voidp");
+    }
+    Delete(go_type);
+
+    String *ct = Getattr(n, "emit:cgotype");
+    if (ct) {
+      *c_struct_type = (bool)Getattr(n, "emit:cgotypestruct");
+      return Copy(ct);
+    }
+
+    String *t = Copy(type);
+    if (SwigType_isarray(t)) {
+      SwigType_del_array(t);
+      SwigType_add_pointer(t);
+    }
+
+    bool add_typedef = true;
+
+    static int count;
+    ++count;
+    ct = NewStringf("swig_type_%d", count);
+
+    String *gct = gcCTypeForGoValue(n, t, ct);
+    Delete(t);
+
+    if (Strncmp(gct, "_gostring_", 10) == 0 || Strncmp(gct, "_goslice_", 9) == 0) {
+      *c_struct_type = true;
+      Setattr(n, "emit:cgotypestruct", type);
+    } else {
+      char *p = Strstr(gct, ct);
+      if (p != NULL && p > (char*)Char(gct) && p[-1] == '*' && p[Len(ct)] == '\0') {
+	// Treat all pointers as void*.  See above.
+	Delete(ct);
+	--count;
+	ct = NewString("swig_voidp");
+	add_typedef = false;
+      }
+
+      if (Strncmp(gct, "bool ", 5) == 0) {
+	// Change the C++ type bool to the C type _Bool.
+	Replace(gct, "bool", "_Bool", DOH_REPLACE_FIRST);
+      }
+      if (Strncmp(gct, "intgo ", 6) == 0) {
+	// We #define intgo to swig_intgo for the cgo comment.
+	Replace(gct, "intgo", "swig_intgo", DOH_REPLACE_FIRST);
+      }
+      p = Strstr(gct, ct);
+      if (p != NULL && p > (char*)Char(gct) && p[-1] == ' ' && p[Len(ct)] == '\0') {
+	String *q = NewStringWithSize(gct, Len(gct) - Len(ct) - 1);
+	if (validIdentifier(q)) {
+	  // This is a simple type name, and we can use it directly.
+	  Delete(ct);
+	  --count;
+	  ct = q;
+	  add_typedef = false;
+	}
+      }
+    }
+    if (add_typedef) {
+      Printv(f_cgo_comment_typedefs, "typedef ", gct, ";\n", NULL);
+    }
+
+    Setattr(n, "emit:cgotype", ct);
+
+    Delete(gct);
+
+    return Copy(ct);
+  }
+
   /* ----------------------------------------------------------------------
    * goWrapperType()
    *
@@ -5330,6 +6485,7 @@ private:
     bool is_member = Strcmp(gt, "_swig_memberptr") == 0;
     bool is_complex64 = Strcmp(gt, "complex64") == 0;
     bool is_complex128 = Strcmp(gt, "complex128") == 0;
+    bool is_bool = false;
     bool is_int8 = false;
     bool is_int16 = false;
     bool is_int = Strcmp(gt, "int") == 0 || Strcmp(gt, "uint") == 0;
@@ -5337,7 +6493,10 @@ private:
     bool is_int64 = false;
     bool is_float32 = false;
     bool is_float64 = false;
-    if ((n != NULL && Getattr(n, "tmap:gotype") != NULL) || hasGoTypemap(n, type)) {
+
+    bool has_typemap = (n != NULL && Getattr(n, "tmap:gotype") != NULL) || hasGoTypemap(n, type);
+    if (has_typemap) {
+      is_bool = Strcmp(gt, "bool") == 0;
       is_int8 = Strcmp(gt, "int8") == 0 || Strcmp(gt, "uint8") == 0 || Strcmp(gt, "byte") == 0;
       is_int16 = Strcmp(gt, "int16") == 0 || Strcmp(gt, "uint16") == 0;
       is_int32 = Strcmp(gt, "int32") == 0 || Strcmp(gt, "uint32") == 0;
@@ -5386,7 +6545,7 @@ private:
       return ret;
     } else {
       SwigType *t = SwigType_typedef_resolve_all(type);
-      if (SwigType_isreference(t)) {
+      if (!has_typemap && SwigType_isreference(t)) {
 	// A const reference to a known type, or to a pointer, is not
 	// mapped to a pointer.
 	SwigType_del_reference(t);
@@ -5424,7 +6583,9 @@ private:
       }
 
       Delete(t);
-      if (is_int8) {
+      if (is_bool) {
+	ret = NewString("bool ");
+      } else if (is_int8) {
 	ret = NewString("char ");
       } else if (is_int16) {
 	ret = NewString("short ");
@@ -5445,7 +6606,7 @@ private:
     }
 
     Append(ret, tail);
-    if (SwigType_isreference(type)) {
+    if (!has_typemap && SwigType_isreference(type)) {
       Append(ret, "* ");
     }
     Append(ret, name);
@@ -5651,6 +6812,7 @@ extern "C" Language *swig_go(void) {
 // Usage message.
 const char * const GO::usage = "\
 Go Options (available with -go)\n\
+     -cgo                - Generate cgo input files\n\
      -gccgo              - Generate code for gccgo rather than 6g/8g\n\
      -go-pkgpath 

- Like gccgo -fgo-pkgpath option\n\ -go-prefix

- Like gccgo -fgo-prefix option\n\ diff --git a/configure.ac b/configure.ac index c2a36fc95..b595de08e 100644 --- a/configure.ac +++ b/configure.ac @@ -2319,109 +2319,102 @@ if test x"${GOBIN}" = xno -o x"${with_alllang}" = xno ; then GO1=false GO12=false GO13=false + GO15=false GOGCC=false + GCCGO= GOOPT= + GCCGOOPT= GOVERSIONOPTION= else if test "x$GOBIN" = xyes; then - AC_CHECK_PROGS(GO, go 6g 8g gccgo) + AC_CHECK_PROGS(GO, go) else GO="$GOBIN" fi + AC_CHECK_PROGS(GCCGO, gccgo) + GOGCC=false + GCCGO= GO1=false GO12=false GO13=false + GO15=false GOOPT= + GCCGOOPT= GOVERSIONOPTION= - if test -n "$GO" ; then - if $GO --help 2>/dev/null | grep gccgo >/dev/null 2>&1 ; then - GOGCC=true - GOVERSIONOPTION=--version - AC_MSG_CHECKING([whether gccgo version is too old]) - go_version=[`$GO $GOVERSIONOPTION | sed -n '1p' | sed -e 's/^.* \([0-9.]*\) *$/\1/' -e 's/[.]//g'`] - if test "x$go_version" = x; then - AC_MSG_RESULT([could not determine gccgo version - disabling Go]) - GO= - elif test "$go_version" -lt 470; then - AC_MSG_RESULT([yes - minimum version is 4.7.0]) - GO= - else - AC_MSG_RESULT([no]) - if test "$go_version" -lt 480; then - GOOPT="-intgosize 32" - else - AC_CHECK_SIZEOF([void *], [4]) - if test "$ac_cv_sizeof_void_p" = "8"; then - GOOPT="-intgosize 64" - else - GOOPT="-intgosize 32" - fi - fi - fi - elif test "`echo $GO | sed -e 's|.*/||'`" = "go"; then - GO1=true - GOVERSIONOPTION=version - GOC=$(sh -c "$(go env) && echo \$GOCHAR")c - go_version=$($GO $GOVERSIONOPTION | sed -e 's/go version //') - AC_MSG_CHECKING([whether go version is too old]) - case $go_version in - go1.0* | go1 ) - AC_MSG_RESULT([yes - minimum version is 1.1]) - GO= - GOOPT="-intgosize 32" - ;; - *) - AC_MSG_RESULT([no]) - if test "$GOC" = "6c"; then - GOOPT="-intgosize 64" - else - GOOPT="-intgosize 32" - fi - ;; - esac - case $go_version in - go1.0* | go1 | go1.1*) - GOOPT="$GOOPT -use-shlib" - ;; - go1.2*) - GO12=true - ;; - *) - GO13=true - ;; - esac + + GO1=true + GOVERSIONOPTION=version + GOC=$(sh -c "$(go env) && echo \$GOCHAR")c + go_version=$($GO $GOVERSIONOPTION | sed -e 's/go version //') + AC_MSG_CHECKING([whether go version is too old]) + case $go_version in + go1.0* | go1 ) + AC_MSG_RESULT([yes - minimum version is 1.1]) + GO= + GOOPT="-intgosize 32" + ;; + *) + AC_MSG_RESULT([no]) + if test "$GOC" = "6c"; then + GOOPT="-intgosize 64" else - GOC=`echo $GO | sed -e 's/g/c/'` - GOVERSIONOPTION=-V - AC_MSG_CHECKING([whether Go ($GO) version is too old]) - AC_MSG_RESULT([yes - minimum version is 1.1]) - GO= - dnl Old code retained for now in case we implement an option for it. - dnl go_version=`$GO $GOVERSIONOPTION 2>/dev/null | sed -e 's/.*version.* \([[0-9]]*\).*/\1/'` - dnl go_min_version=7077 - dnl if test "$go_version" != "" -a "$go_version" -lt $go_min_version; then - dnl AC_MSG_RESULT([yes - minimum version is $go_min_version]) - dnl GO= - dnl else - dnl AC_MSG_RESULT([no]) - dnl fi GOOPT="-intgosize 32" - GO12=false - GO13=false + fi + ;; + esac + case $go_version in + go1.0* | go1 | go1.1*) + GOOPT="$GOOPT -use-shlib" + ;; + go1.2*) + GO12=true + ;; + go1.3* | go1.4*) + GO13=true + ;; + *) + GO15=true + ;; + esac + + if $GCCGO --help 2>/dev/null | grep gccgo >/dev/null 2>&1 ; then + AC_MSG_CHECKING([whether gccgo version is too old]) + go_version=[`$GO $GOVERSIONOPTION | sed -n '1p' | sed -e 's/^.* \([0-9.]*\) *$/\1/' -e 's/[.]//g'`] + if test "x$go_version" = x; then + AC_MSG_RESULT([could not determine gccgo version]) + GCCGO= + elif test "$go_version" -lt 470; then + AC_MSG_RESULT([yes - minimum version is 4.7.0]) + GCCGO= + else + AC_MSG_RESULT([no]) + if test "$go_version" -lt 480; then + GCCGOOPT="-intgosize 32" + else + AC_CHECK_SIZEOF([void *], [4]) + if test "$ac_cv_sizeof_void_p" = "8"; then + GCCGOOPT="-intgosize 64" + else + GCCGOOPT="-intgosize 32" + fi + fi fi fi fi AC_SUBST(GOGCC) +AC_SUBST(GCCGO) AC_SUBST(GO) AC_SUBST(GOC) AC_SUBST(GO1) AC_SUBST(GO12) AC_SUBST(GO13) +AC_SUBST(GO15) AC_SUBST(GOOPT) +AC_SUBST(GCCGOOPT) AC_SUBST(GOVERSIONOPTION) #----------------------------------------------------------------