diff --git a/misc/swig/callback/Makefile b/misc/swig/callback/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..fde0d107bbd70982535ca2cdd83b1f1a14fdb4c2
--- /dev/null
+++ b/misc/swig/callback/Makefile
@@ -0,0 +1,17 @@
+# Copyright 2011 The Go Authors.  All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../src/Make.inc
+
+TARG=swig/callback
+SWIGFILES=\
+	callback.swigcxx
+
+CLEANFILES+=run
+
+include ../../../src/Make.pkg
+
+%: install %.go
+	$(GC) $*.go
+	$(LD) $(SWIG_RPATH) -o $@ $*.$O
diff --git a/misc/swig/callback/callback.h b/misc/swig/callback/callback.h
new file mode 100644
index 0000000000000000000000000000000000000000..80232a8b3d397fdff1ce0bbbb6718e3f78e93816
--- /dev/null
+++ b/misc/swig/callback/callback.h
@@ -0,0 +1,24 @@
+// Copyright 2011 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+class Callback {
+public:
+	virtual ~Callback() { }
+	virtual std::string run() { return "Callback::run"; }
+};
+
+class Caller {
+private:
+	Callback *callback_;
+public:
+	Caller(): callback_(0) { }
+	~Caller() { delCallback(); }
+	void delCallback() { delete callback_; callback_ = 0; }
+	void setCallback(Callback *cb) { delCallback(); callback_ = cb; }
+	std::string call() {
+		if (callback_ != 0)
+			return callback_->run();
+		return "";
+	}
+};
diff --git a/misc/swig/callback/callback.swigcxx b/misc/swig/callback/callback.swigcxx
new file mode 100644
index 0000000000000000000000000000000000000000..0c97ef1016c0322f23c29157575ec4df1345ec99
--- /dev/null
+++ b/misc/swig/callback/callback.swigcxx
@@ -0,0 +1,18 @@
+/* Copyright 2011 The Go Authors.  All rights reserved.
+   Use of this source code is governed by a BSD-style
+   license that can be found in the LICENSE file.  */
+
+/* An example of writing a C++ virtual function in Go.  */
+
+%module(directors="1") callback
+
+%{
+#include <string>
+#include "callback.h"
+%}
+
+%include "std_string.i"
+
+%feature("director");
+
+%include "callback.h"
diff --git a/misc/swig/callback/run b/misc/swig/callback/run
new file mode 100755
index 0000000000000000000000000000000000000000..de150ed05f3d9869315c95ac6c6a3788bdf37924
Binary files /dev/null and b/misc/swig/callback/run differ
diff --git a/misc/swig/callback/run.go b/misc/swig/callback/run.go
new file mode 100644
index 0000000000000000000000000000000000000000..a76e636cb522d5ed8e6fb19d501b6fb323e780db
--- /dev/null
+++ b/misc/swig/callback/run.go
@@ -0,0 +1,39 @@
+// Copyright 2011 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+	"swig/callback"
+	"fmt"
+)
+
+type GoCallback struct{}
+
+func (p *GoCallback) Run() string {
+	return "GoCallback.Run"
+}
+
+func main() {
+	c := callback.NewCaller()
+	cb := callback.NewCallback()
+
+	c.SetCallback(cb)
+	s := c.Call()
+	fmt.Println(s)
+	if s != "Callback::run" {
+		panic(s)
+	}
+	c.DelCallback()
+
+	cb = callback.NewDirectorCallback(&GoCallback{})
+	c.SetCallback(cb)
+	s = c.Call()
+	fmt.Println(s)
+	if s != "GoCallback.Run" {
+		panic(s)
+	}
+	c.DelCallback()
+	callback.DeleteDirectorCallback(cb)
+}
diff --git a/misc/swig/stdio/Makefile b/misc/swig/stdio/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..e7d330587c486634d89b63774e32fa1c76bbc9d8
--- /dev/null
+++ b/misc/swig/stdio/Makefile
@@ -0,0 +1,17 @@
+# Copyright 2011 The Go Authors.  All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../src/Make.inc
+
+TARG=swig/file
+SWIGFILES=\
+	file.swig
+
+CLEANFILES+=hello
+
+include ../../../src/Make.pkg
+
+%: install %.go
+	$(GC) $*.go
+	$(LD) $(SWIG_RPATH) -o $@ $*.$O
diff --git a/misc/swig/stdio/file.swig b/misc/swig/stdio/file.swig
new file mode 100644
index 0000000000000000000000000000000000000000..57c623f8f7b74c287a795637f2daa37386aafd8a
--- /dev/null
+++ b/misc/swig/stdio/file.swig
@@ -0,0 +1,11 @@
+/* Copyright 2011 The Go Authors.  All rights reserved.
+   Use of this source code is governed by a BSD-style
+   license that can be found in the LICENSE file.  */
+
+/* A trivial example of wrapping a C library using SWIG.  */
+
+%{
+#include <stdio.h>
+%}
+
+int puts(const char *);
diff --git a/misc/swig/stdio/hello b/misc/swig/stdio/hello
new file mode 100755
index 0000000000000000000000000000000000000000..10c55631f8a4209a38a36d084a292dffbfa38be9
Binary files /dev/null and b/misc/swig/stdio/hello differ
diff --git a/misc/swig/stdio/hello.go b/misc/swig/stdio/hello.go
new file mode 100644
index 0000000000000000000000000000000000000000..eec294278669ba8490f5dc07a446c2d523ff2934
--- /dev/null
+++ b/misc/swig/stdio/hello.go
@@ -0,0 +1,11 @@
+// Copyright 2011 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "swig/file"
+
+func main() {
+	file.Puts("Hello, world")
+}
diff --git a/src/Make.pkg b/src/Make.pkg
index 3d616ca9992dff3603fc1dfe4cb2fb2210c8befe..dcdb09132e012f52b37bdfad7eedad6c086386b6 100644
--- a/src/Make.pkg
+++ b/src/Make.pkg
@@ -41,6 +41,14 @@ CGO_OFILES+=$(patsubst %.go,%.cgo2.o,$(CGOFILES)) _cgo_export.o
 OFILES+=_cgo_defun.$O _cgo_import.$O $(CGO_OFILES)
 endif
 
+ifdef SWIGFILES
+GOFILES+=$(patsubst %.swig,_obj/%.go,$(patsubst %.swigcxx,%.swig,$(SWIGFILES)))
+OFILES+=$(patsubst %.swig,_obj/%_gc.$O,$(patsubst %.swigcxx,%.swig,$(SWIGFILES)))
+SWIG_PREFIX=$(subst /,-,$(TARG))
+SWIG_SOS+=$(patsubst %.swig,_obj/$(SWIG_PREFIX)-%.so,$(patsubst %.swigcxx,%.swig,$(SWIGFILES)))
+INSTALLFILES+=$(patsubst %.swig,$(pkgdir)/swig/$(SWIG_PREFIX)-%.so,$(patsubst %.swigcxx,%.swig,$(SWIGFILES)))
+endif
+
 PREREQ+=$(patsubst %,%.make,$(DEPS))
 
 coverage:
@@ -109,6 +117,16 @@ dir:
 #	_obj/x.cgo2.c	- C implementations compiled with gcc to create a dynamic library
 #
 
+ifneq ($(CGOFILES)$(SWIGFILES),)
+# Have to run gcc with the right size argument on hybrid 32/64 machines.
+_CGO_CFLAGS_386=-m32
+_CGO_CFLAGS_amd64=-m64
+_CGO_LDFLAGS_freebsd=-shared -lpthread -lm
+_CGO_LDFLAGS_linux=-shared -lpthread -lm
+_CGO_LDFLAGS_darwin=-dynamiclib -Wl,-undefined,dynamic_lookup
+_CGO_LDFLAGS_windows=-shared -lm -mthreads
+endif
+
 ifdef CGOFILES
 _obj/_cgo_run: $(CGOFILES)
 	@mkdir -p _obj
@@ -158,14 +176,6 @@ _obj/_cgo_import.c: _cgo1_.o
 # added _cgo_defun.$O to $OFILES, and added the installed copy of
 # package_x.so (built from x.cgo2.c) to $(INSTALLFILES).
 
-# Have to run gcc with the right size argument on hybrid 32/64 machines.
-_CGO_CFLAGS_386=-m32
-_CGO_CFLAGS_amd64=-m64
-_CGO_LDFLAGS_freebsd=-shared -lpthread -lm
-_CGO_LDFLAGS_linux=-shared -lpthread -lm
-_CGO_LDFLAGS_darwin=-dynamiclib -Wl,-undefined,dynamic_lookup
-_CGO_LDFLAGS_windows=-shared -lm -mthreads
-
 # Have to compile the runtime header.
 RUNTIME_CFLAGS=-I$(pkgdir)
 
@@ -173,6 +183,54 @@ RUNTIME_CFLAGS=-I$(pkgdir)
 _cgo_defun.$O: _obj/_cgo_defun.c
 	$(CC) $(CFLAGS) $(RUNTIME_CFLAGS) -I . -o "$@" _obj/_cgo_defun.c
 
+# To use swig in a Go package, add a line
+#
+#	SWIGFILES=x.swig
+#
+# to the main Makefile.  This signals that SWIG should process the
+#.swig file when building the package.
+#
+# To wrap C code, use an extension of .swig.  To wrap C++ code, use an
+# extension of .swigcxx.
+#
+#	SWIGFILES=myclib.swig mycxxlib.swigcxx
+
+ifdef SWIGFILES
+_obj/%._swig_run _obj/%.go _obj/%_gc.c _obj/%_wrap.c: %.swig
+	@mkdir -p _obj
+	swig -go -module $* -soname $(SWIG_PREFIX)-$*.so -o _obj/$*_wrap.c -outdir _obj $<
+
+_obj/%._swig_run _obj/%.go _obj/%_gc.c _obj/%_wrap.cxx: %.swigcxx
+	@mkdir -p _obj
+	swig -go -c++ -module $* -soname $(SWIG_PREFIX)-$*.so -o _obj/$*_wrap.cxx -outdir _obj $<
+
+_obj/%_gc.$O: _obj/%_gc.c
+	$(CC) $(CFLAGS) -I . -I$(pkgdir) -o "$@" _obj/$*_gc.c
+
+_obj/%_wrap.o: _obj/%_wrap.c
+	$(HOST_CC) $(_CGO_CFLAGS_$(GOARCH)) -I . -g -fPIC -O2 -o $@ -c $^ $(SWIG_CFLAGS)
+
+HOST_CXX=g++
+
+_obj/%_wrapcxx.o: _obj/%_wrap.cxx
+	$(HOST_CXX) $(_CGO_CFLAGS_$(GOARCH)) -I . -g -fPIC -O2 -o $@ -c $^ $(SWIG_CXXFLAGS)
+
+_obj/$(SWIG_PREFIX)-%.so: _obj/%_wrap.o
+	$(HOST_CC) $(_CGO_CFLAGS_$(GOARCH)) -o $@ $^ $(SWIG_LDFLAGS) $(_CGO_LDFLAGS_$(GOOS)) $(_SWIG_LDFLAGS_$(GOOS))
+
+_obj/$(SWIG_PREFIX)-%.so: _obj/%_wrapcxx.o
+	$(HOST_CXX) $(_CGO_CFLAGS_$(GOARCH)) -o $@ $^ $(SWIG_LDFLAGS) $(_CGO_LDFLAGS_$(GOOS)) $(_SWIG_LDFLAGS_$(GOOS))
+
+$(pkgdir)/swig/$(SWIG_PREFIX)-%.so: _obj/$(SWIG_PREFIX)-%.so
+	@test -d $(QUOTED_GOROOT)/pkg && mkdir -p $(pkgdir)/swig
+	cp $< "$@"
+
+all: $(SWIG_SOS)
+
+SWIG_RPATH=-r $(pkgdir)/swig
+
+endif
+
 # Generic build rules.
 # These come last so that the rules above can override them
 # for more specific file names.