diff options
author | Ian Lance Taylor <iant@golang.org> | 2022-03-08 15:15:05 -0800 |
---|---|---|
committer | Ian Lance Taylor <iant@golang.org> | 2022-03-08 15:15:05 -0800 |
commit | 70d530adfc4f4e0697179f6eb0b8a147a73d5889 (patch) | |
tree | cc6f897eff4ef3da25cf6e873bbda876002a5437 | |
parent | 7ebe5cead32087ed6835a6e5715ac5cbf8c110f7 (diff) | |
download | swig-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.go | 4 | ||||
-rw-r--r-- | Examples/test-suite/go_inout.i | 2 | ||||
-rw-r--r-- | Lib/go/goruntime.swg | 11 | ||||
-rw-r--r-- | Source/Modules/go.cxx | 48 |
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); |