summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2022-03-08 15:15:05 -0800
committerIan Lance Taylor <iant@golang.org>2022-03-08 15:15:05 -0800
commit70d530adfc4f4e0697179f6eb0b8a147a73d5889 (patch)
treecc6f897eff4ef3da25cf6e873bbda876002a5437
parent7ebe5cead32087ed6835a6e5715ac5cbf8c110f7 (diff)
downloadswig-70d530adfc4f4e0697179f6eb0b8a147a73d5889.tar.gz
swig -go: treat a nil argument as NULL
Let Go code pass "nil" when calling a C++ function that accepts a pointer to a class. The Go "nil" will be treated as a C++ "nullptr". Fixes #2203
-rw-r--r--Examples/test-suite/go/go_inout_runme.go4
-rw-r--r--Examples/test-suite/go_inout.i2
-rw-r--r--Lib/go/goruntime.swg11
-rw-r--r--Source/Modules/go.cxx48
4 files changed, 53 insertions, 12 deletions
diff --git a/Examples/test-suite/go/go_inout_runme.go b/Examples/test-suite/go/go_inout_runme.go
index 2dc5b9908..84dec7a0b 100644
--- a/Examples/test-suite/go/go_inout_runme.go
+++ b/Examples/test-suite/go/go_inout_runme.go
@@ -50,4 +50,8 @@ func main() {
fmt.Println("for c2.M got", pm, "want", want)
panic(pm)
}
+
+ c1 := go_inout.NewC1()
+ c2.M2(c1)
+ c2.M2(nil)
}
diff --git a/Examples/test-suite/go_inout.i b/Examples/test-suite/go_inout.i
index 0bcb979ef..bb73f1b90 100644
--- a/Examples/test-suite/go_inout.i
+++ b/Examples/test-suite/go_inout.i
@@ -239,5 +239,7 @@ class C1 {
};
class C2 : public C1 {
+ public:
+ void M2(C1*) {}
};
%}
diff --git a/Lib/go/goruntime.swg b/Lib/go/goruntime.swg
index c3401b1a8..90685ab95 100644
--- a/Lib/go/goruntime.swg
+++ b/Lib/go/goruntime.swg
@@ -149,6 +149,17 @@ type _swig_fnptr *byte
type _swig_memberptr *byte
%}
+/* Convert a Go interface value into a C++ pointer. */
+
+%insert(go_header) %{
+func getSwigcptr(v interface { Swigcptr() uintptr }) uintptr {
+ if v == nil {
+ return 0
+ }
+ return v.Swigcptr()
+}
+%}
+
/* For directors we need C++ to track a Go pointer. Since we can't
pass a Go pointer into C++, we use a map to track the pointers on
the Go side. */
diff --git a/Source/Modules/go.cxx b/Source/Modules/go.cxx
index 12f0dd747..c2e95228d 100644
--- a/Source/Modules/go.cxx
+++ b/Source/Modules/go.cxx
@@ -1262,9 +1262,15 @@ private:
String *goin = goGetattr(p, "tmap:goin");
if (goin == NULL) {
- Printv(f_go_wrappers, "\t", ivar, " := ", ln, NULL);
+ Printv(f_go_wrappers, "\t", ivar, " := ", NULL);
+ bool need_close = false;
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, "getSwigcptr(", NULL);
+ need_close = true;
+ }
+ Printv(f_go_wrappers, ln, NULL);
+ if (need_close) {
+ Printv(f_go_wrappers, ")", NULL);
}
Printv(f_go_wrappers, "\n", NULL);
Setattr(p, "emit:goinput", ln);
@@ -2506,7 +2512,7 @@ private:
Printv(interfaces, "\tSwigIs", go_base_name, "()\n", NULL);
Printv(f_go_wrappers, "func (p ", go_type_name, ") SwigGet", go_base_name, "() ", go_base_type, " {\n", NULL);
- Printv(f_go_wrappers, "\treturn ", go_base_type_name, "(p.Swigcptr())\n", NULL);
+ Printv(f_go_wrappers, "\treturn ", go_base_type_name, "(getSwigcptr(p))\n", NULL);
Printv(f_go_wrappers, "}\n\n", NULL);
Printv(interfaces, "\tSwigGet", go_base_name, "() ", go_base_type, "\n", NULL);
@@ -2708,7 +2714,7 @@ private:
Printv(f_go_wrappers, "}\n\n", NULL);
Printv(f_go_wrappers, "func (p *", director_struct_name, ") Swigcptr() uintptr {\n", NULL);
- Printv(f_go_wrappers, "\treturn p.", go_type_name, ".Swigcptr()\n", NULL);
+ Printv(f_go_wrappers, "\treturn getSwigcptr(p.", go_type_name, ")\n", NULL);
Printv(f_go_wrappers, "}\n\n", NULL);
Printv(f_go_wrappers, "func (p *", director_struct_name, ") SwigIs", go_name, "() {\n", NULL);
@@ -2866,9 +2872,15 @@ private:
String *goin = goGetattr(p, "tmap:goin");
if (goin == NULL) {
- Printv(f_go_wrappers, "\t", ivar, " := ", ln, NULL);
+ Printv(f_go_wrappers, "\t", ivar, " := ", NULL);
+ bool need_close = false;
if (goTypeIsInterface(p, pt)) {
- Printv(f_go_wrappers, ".Swigcptr()", NULL);
+ Printv(f_go_wrappers, "getSwigcptr(", NULL);
+ need_close = true;
+ }
+ Printv(f_go_wrappers, ln, NULL);
+ if (need_close) {
+ Printv(f_go_wrappers, ")", NULL);
}
Printv(f_go_wrappers, "\n", NULL);
} else {
@@ -3461,9 +3473,15 @@ private:
// the goin typemap.
String *goin = goGetattr(p, "tmap:goin");
if (goin == NULL) {
- Printv(f_go_wrappers, "\t", ivar, " := ", ln, NULL);
+ Printv(f_go_wrappers, "\t", ivar, " := ", NULL);
+ bool need_close = false;
if (goTypeIsInterface(p, pt)) {
- Printv(f_go_wrappers, ".Swigcptr()", NULL);
+ Printv(f_go_wrappers, "getSwigcptr(", NULL);
+ need_close = true;
+ }
+ Printv(f_go_wrappers, ln, NULL);
+ if (need_close) {
+ Printv(f_go_wrappers, ")", NULL);
}
Printv(f_go_wrappers, "\n", NULL);
} else {
@@ -3709,9 +3727,15 @@ private:
String *goin = goGetattr(p, "tmap:goin");
if (goin == NULL) {
- Printv(f_go_wrappers, "\t", ivar, " := ", ln, NULL);
+ Printv(f_go_wrappers, "\t", ivar, " := ", NULL);
+ bool need_close = false;
if (goTypeIsInterface(p, pt)) {
- Printv(f_go_wrappers, ".Swigcptr()", NULL);
+ Printv(f_go_wrappers, "getSwigcptr(", NULL);
+ need_close = true;
+ }
+ Printv(f_go_wrappers, ln, NULL);
+ if (need_close) {
+ Printv(f_go_wrappers, ")", NULL);
}
Printv(f_go_wrappers, "\n", NULL);
} else {
@@ -3830,7 +3854,7 @@ private:
if (SwigType_type(result) != T_VOID) {
Printv(call, "swig_r = ", NULL);
if (result_is_interface) {
- Printv(call, result_wrapper, "(", NULL);
+ Printv(call, result_wrapper, "(getSwigcptr(", NULL);
}
}
Printv(call, "swig_p.", go_with_over_name, "(", NULL);
@@ -3890,7 +3914,7 @@ private:
Printv(call, ")", NULL);
if (result_is_interface) {
- Printv(call, ".Swigcptr())", NULL);
+ Printv(call, "))", NULL);
}
Printv(call, "\n", NULL);