summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2022-03-05 21:57:36 -0800
committerIan Lance Taylor <iant@golang.org>2022-03-05 21:57:36 -0800
commit27bdbc1f05c7c656c9d0cafdea225ab3cf017f89 (patch)
tree4875419260c4fe04c98efd0696d24ab06949f96e
parent4499422308b9fdb7c93b10c51a828285cb614d34 (diff)
downloadswig-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.go32
-rw-r--r--Examples/test-suite/go_director_inout.i25
-rw-r--r--Lib/go/go.swg48
-rw-r--r--Source/Modules/go.cxx29
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