diff options
author | Ian Lance Taylor <iant@golang.org> | 2022-03-05 21:57:36 -0800 |
---|---|---|
committer | Ian Lance Taylor <iant@golang.org> | 2022-03-05 21:57:36 -0800 |
commit | 27bdbc1f05c7c656c9d0cafdea225ab3cf017f89 (patch) | |
tree | 4875419260c4fe04c98efd0696d24ab06949f96e | |
parent | 4499422308b9fdb7c93b10c51a828285cb614d34 (diff) | |
download | swig-27bdbc1f05c7c656c9d0cafdea225ab3cf017f89.tar.gz |
swig -go: treat non-const references as pointers
Also clean up the handling of int* and int& to convert between the C
type int and the Go type int, which are often different sizes.
Fixes #2210
-rw-r--r-- | Examples/test-suite/go/go_director_inout_runme.go | 32 | ||||
-rw-r--r-- | Examples/test-suite/go_director_inout.i | 25 | ||||
-rw-r--r-- | Lib/go/go.swg | 48 | ||||
-rw-r--r-- | Source/Modules/go.cxx | 29 |
4 files changed, 115 insertions, 19 deletions
diff --git a/Examples/test-suite/go/go_director_inout_runme.go b/Examples/test-suite/go/go_director_inout_runme.go index 171b3c223..f2be9d30b 100644 --- a/Examples/test-suite/go/go_director_inout_runme.go +++ b/Examples/test-suite/go/go_director_inout_runme.go @@ -14,6 +14,26 @@ func (p *GoMyClass) Adjust(m map[string]interface{}) wrap.GoRetStruct { return wrap.GoRetStruct{s} } +func (p *GoMyClass) S1(s string) { + if s != "S1" { + panic(s) + } +} + +func (p *GoMyClass) S2(s *string) { + if *s != "S2" { + panic(s) + } + *s = "R2" +} + +func (p *GoMyClass) S3(s *string) { + if *s != "S3" { + panic(s) + } + *s = "R3" +} + func main() { a := wrap.NewDirectorMyClass(&GoMyClass{}) m := map[string]interface{}{ @@ -24,6 +44,18 @@ func main() { panic(s) } + a.S1("S1") + str := "S2" + a.S2(&str) + if str != "R2" { + panic(str) + } + str = "S3" + a.S3(&str) + if str != "R3" { + panic(str) + } + a = wrap.NewDirectorMyClass(nil) s = a.Adjust(m) if s.Str != `{"first":"second"}` { diff --git a/Examples/test-suite/go_director_inout.i b/Examples/test-suite/go_director_inout.i index 5a7fbdf89..708bd7c87 100644 --- a/Examples/test-suite/go_director_inout.i +++ b/Examples/test-suite/go_director_inout.i @@ -2,6 +2,8 @@ %module(directors="1") go_director_inout +%include <std_string.i> + %{ #include <string> %} @@ -108,6 +110,25 @@ type GoRetStruct struct { $1.str.assign($input.p, $input.n); %} +%typemap(directorin) std::string & (_gostring_ temp) { + $input = &temp; + temp.p = (char *) $1.data(); + temp.n = $1.size(); +} +%typemap(directorargout) std::string & { + _gostring_ *tmp = $input; + $1.assign(tmp->p, tmp->p + tmp->n); +} + +%typemap(directorin) std::string * (_gostring_ temp) { + $input = &temp; + $input->p = (char *) $1->data(); + $input->n = $1->size(); +} +%typemap(directorargout) std::string * { + $1->assign($input->p, $input->p + $input->n); +} + %feature("director") MyClass; %inline @@ -121,6 +142,10 @@ class MyClass { r.str = s.str; return r; } + + virtual void S1(std::string s) = 0; + virtual void S2(std::string& s) = 0; + virtual void S3(std::string* s) = 0; }; %} diff --git a/Lib/go/go.swg b/Lib/go/go.swg index c225ed9ad..f955ba52f 100644 --- a/Lib/go/go.swg +++ b/Lib/go/go.swg @@ -453,9 +453,12 @@ %} %typemap(freearg) - char *, char *&, char[ANY], char[] + char *, char[ANY], char[] %{ free($1); %} +%typemap(freearg) char *& +%{ free(*$1); %} + %typemap(out,fragment="AllocateString") char *, char *&, char[ANY], char[] %{ $result = Swig_AllocateString((char*)$1, $1 ? strlen((char*)$1) : 0); %} @@ -520,6 +523,44 @@ $2 = ($2_ltype)$input.n; %} +/* The int & type needs to convert to intgo. */ + +%typemap(gotype) int & "*int" + +%typemap(in) int & (int e) +%{ + e = (int)*$input; + $1 = &e; +%} + +%typemap(out) int & +%{ $result = new intgo(*$1); %} + +%typemap(argout) int & +%{ *$input = (intgo)e$argnum; %} + +%typemap(goout) int & "" + +%typemap(directorin) int & (intgo e) +%{ + e = (intgo)$1; + $input = &e; +%} + +%typemap(godirectorin) int & "" + +%typemap(directorout) int & +%{ + $*1_ltype f = ($*1_ltype)*$input; + $result = ($1_ltype)&f; +%} + +%typemap(directorargout) int & +%{ $1 = (int)*$input; %} + +%typemap(argout) const int & "" +%typemap(directorargout) const int & "" + /* Enums. We can't do the right thing for enums in typemap(gotype) so we deliberately don't define them. The right thing would be to capitalize the name. This is instead done in go.cxx. */ @@ -552,10 +593,7 @@ %typemap(godirectorin) enum SWIGTYPE & "" %typemap(directorout) enum SWIGTYPE & -%{ - $*1_ltype f = ($*1_ltype)*$input; - $result = ($1_ltype)&f; -%} +%{ $result = $input; %} /* Arbitrary type. This is a type passed by value in the C/C++ code. We convert it to a pointer for the Go code. Note that all basic diff --git a/Source/Modules/go.cxx b/Source/Modules/go.cxx index 0c039fcfc..12f0dd747 100644 --- a/Source/Modules/go.cxx +++ b/Source/Modules/go.cxx @@ -377,7 +377,7 @@ private: /* --------------------------------------------------------------------- * top() * - * For 6g/8g, we are going to create the following files: + * For gc, we are going to create the following files: * * 1) A .c or .cxx file compiled with gcc. This file will contain * function wrappers. Each wrapper will take a pointer to a @@ -5284,7 +5284,7 @@ private: * gcCTypeForGoValue() * * Given a type, return the C/C++ type which will be used to catch - * the value in Go. This is the 6g/8g version. + * the value in Go. This is the gc version. * ---------------------------------------------------------------------- */ String *gcCTypeForGoValue(Node *n, SwigType *type, String *name) { @@ -5293,7 +5293,19 @@ private: String *tail = NewString(""); SwigType *t = SwigType_typedef_resolve_all(type); - if (!SwigType_isreference(t)) { + bool is_const_ref = false; + if (SwigType_isreference(t)) { + SwigType* tt = Copy(t); + SwigType_del_reference(tt); + if (SwigType_isqualifier(tt)) { + String* q = SwigType_parm(tt); + if (Strcmp(q, "const") == 0) { + is_const_ref = true; + } + } + Delete(tt); + } + if (!is_const_ref) { while (Strncmp(gt, "*", 1) == 0) { Replace(gt, "*", "", DOH_REPLACE_FIRST); Printv(tail, "*", NULL); @@ -5437,17 +5449,6 @@ private: } /* ---------------------------------------------------------------------- - * gccgoCTypeForGoValue() - * - * Given a type, return the C/C++ type which will be used to catch - * the value in Go. This is the gccgo version. - * ---------------------------------------------------------------------- */ - - String *gccgoCTypeForGoValue(Node *n, SwigType *type, String *name) { - return gcCTypeForGoValue(n, type, name); - } - - /* ---------------------------------------------------------------------- * goTypeIsInterface * * Return whether this C++ type is represented as an interface type |