diff --git a/CHANGES.current b/CHANGES.current index 1945e9292..ca7503d41 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -5,6 +5,9 @@ See the RELEASENOTES file for a summary of changes in each release. Version 3.0.0 (in progress) ============================ +2014-01-21: ianlancetaylor + [Go] Add %go_import directive. + 2014-01-21: ianlancetaylor [Go] Add support for Go 1.3, not yet released. diff --git a/Doc/Manual/Go.html b/Doc/Manual/Go.html index 43bfc6971..240db2b61 100644 --- a/Doc/Manual/Go.html +++ b/Doc/Manual/Go.html @@ -666,9 +666,31 @@ func (arg SwigcptrWrapped_MyClass) GetAValue() (int, bool) { few, then you might as well define your own struct that includes the swig-wrapped object, instead of adding methods to the swig-generated object.

-

This only works if your wrappers do not need to import other go modules. -There is at present no way to insert import statements in the correct place -in swig-generated go. If you need to do that, you must put your go code -in a separate file.

+

If you need to import other go packages, you can do this with +%go_import. For example,

+
+
+%go_import("fmt", _ "unusedPackage", rp "renamed/package")
+
+%insert(go_wrapper) %{
+
+func foo() {
+  fmt.Println("Some string:", rp.GetString())
+}
+
+// Importing the same package twice is permitted,
+// Go code will be generated with only the first instance of the import.
+%go_import("fmt")
+
+%insert(go_wrapper) %{
+
+func bar() {
+  fmt.Println("Hello world!")
+}
+
+%}
+
+
+ diff --git a/Lib/go/go.swg b/Lib/go/go.swg index b9086caac..c9dc34361 100644 --- a/Lib/go/go.swg +++ b/Lib/go/go.swg @@ -4,6 +4,9 @@ * Go configuration module. * ------------------------------------------------------------ */ +/* Code insertion directives */ +#define %go_import(...) %insert(go_imports) %{__VA_ARGS__%} + /* Basic types */ %typemap(gotype) bool, const bool & "bool" diff --git a/Lib/go/goruntime.swg b/Lib/go/goruntime.swg index 3e639cdc2..612f83086 100644 --- a/Lib/go/goruntime.swg +++ b/Lib/go/goruntime.swg @@ -192,30 +192,26 @@ static _gostring_ _swig_makegostring(const char *p, size_t l) { #ifndef SWIGGO_GCCGO -%insert(go_header) %{ - -import _ "runtime/cgo" -import "unsafe" - -type _ unsafe.Pointer - -%} +%go_import("unsafe", _ "runtime/cgo") #else +%go_import("syscall", "unsafe") + %insert(go_header) %{ -import "syscall" -import "unsafe" - type _ syscall.Sockaddr -type _ unsafe.Pointer - %} #endif +%insert(go_header) %{ + +type _ unsafe.Pointer + +%} + /* 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 36e5d11d3..77c5418d2 100644 --- a/Source/Modules/go.cxx +++ b/Source/Modules/go.cxx @@ -45,6 +45,7 @@ class GO:public Language { File *f_c_init; File *f_c_directors; File *f_c_directors_h; + File *f_go_imports; File *f_go_runtime; File *f_go_header; File *f_go_wrappers; @@ -84,6 +85,9 @@ class GO:public Language { // A hash table of classes which were defined. The index is a Go // type name. Hash *defined_types; + // A hash table of all the go_imports already imported. The index is a full + // import name e.g. '"runtime"' or '_ "runtime/cgo"' or 'sc "syscall"'. + Hash *go_imports; public: GO():package(NULL), @@ -104,6 +108,7 @@ public: f_c_init(NULL), f_c_directors(NULL), f_c_directors_h(NULL), + f_go_imports(NULL), f_go_runtime(NULL), f_go_header(NULL), f_go_wrappers(NULL), @@ -120,7 +125,8 @@ public: making_variable_wrappers(false), is_static_member_function(false), undefined_types(NULL), - defined_types(NULL) { + defined_types(NULL), + go_imports(NULL) { director_multiple_inheritance = 1; director_language = 1; director_prot_ctor_code = NewString("_swig_gopanic(\"accessing abstract class or protected constructor\");"); @@ -362,6 +368,7 @@ private: f_c_wrappers = NewString(""); f_c_init = NewString(""); f_c_directors = NewString(""); + f_go_imports = NewString(""); f_go_runtime = NewString(""); f_go_header = NewString(""); f_go_wrappers = NewString(""); @@ -379,6 +386,7 @@ private: Swig_register_filebyname("director", f_c_directors); Swig_register_filebyname("director_h", f_c_directors_h); Swig_register_filebyname("go_begin", f_go_begin); + Swig_register_filebyname("go_imports", f_go_imports); Swig_register_filebyname("go_runtime", f_go_runtime); Swig_register_filebyname("go_header", f_go_header); Swig_register_filebyname("go_wrapper", f_go_wrappers); @@ -445,11 +453,14 @@ private: undefined_types = NewHash(); defined_types = NewHash(); + go_imports = NewHash(); // Emit code. Language::top(n); + Delete(go_imports); + // Write out definitions for the types not defined by SWIG. Printv(f_go_wrappers, "\n", NULL); @@ -493,6 +504,7 @@ private: Dump(f_c_runtime, f_c_begin); Dump(f_c_wrappers, f_c_begin); Dump(f_c_init, f_c_begin); + Dump(f_go_imports, f_go_begin); Dump(f_go_header, f_go_begin); Dump(f_go_runtime, f_go_begin); Dump(f_go_wrappers, f_go_begin); @@ -506,6 +518,7 @@ private: Delete(f_c_header); Delete(f_c_wrappers); Delete(f_c_init); + Delete(f_go_imports); Delete(f_go_runtime); Delete(f_go_header); Delete(f_go_wrappers); @@ -535,7 +548,10 @@ private: String *hold_import = imported_package; String *modname = Getattr(n, "module"); if (modname) { - Printv(f_go_begin, "import \"", modname, "\"\n", NULL); + if (!Getattr(go_imports, modname)) { + Setattr(go_imports, modname, modname); + Printv(f_go_imports, "import \"", modname, "\"\n", NULL); + } imported_package = modname; saw_import = true; } @@ -544,6 +560,31 @@ private: return r; } + /* ---------------------------------------------------------------------- + * Language::insertDirective() + * + * If the section is go_imports, store them for later. + * ---------------------------------------------------------------------- */ + virtual int insertDirective(Node *n) { + char *section = Char(Getattr(n, "section")); + if ((ImportMode && !Getattr(n, "generated")) || + !section || (strcmp(section, "go_imports") != 0)) { + return Language::insertDirective(n); + } + + char *code = Char(Getattr(n, "code")); + char *pch = strtok(code, ","); + while (pch != NULL) { + // Do not import same thing more than once. + if (!Getattr(go_imports, pch)) { + Setattr(go_imports, pch, pch); + Printv(f_go_imports, "import ", pch, "\n", NULL); + } + pch = strtok(NULL, ","); + } + return SWIG_OK; + } + /* ---------------------------------------------------------------------- * functionWrapper() *