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
This commit is contained in:
Ian Lance Taylor 2022-03-05 21:57:36 -08:00
commit 27bdbc1f05
4 changed files with 115 additions and 19 deletions

View file

@ -14,6 +14,26 @@ func (p *GoMyClass) Adjust(m map[string]interface{}) wrap.GoRetStruct {
return wrap.GoRetStruct{s} 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() { func main() {
a := wrap.NewDirectorMyClass(&GoMyClass{}) a := wrap.NewDirectorMyClass(&GoMyClass{})
m := map[string]interface{}{ m := map[string]interface{}{
@ -24,6 +44,18 @@ func main() {
panic(s) 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) a = wrap.NewDirectorMyClass(nil)
s = a.Adjust(m) s = a.Adjust(m)
if s.Str != `{"first":"second"}` { if s.Str != `{"first":"second"}` {

View file

@ -2,6 +2,8 @@
%module(directors="1") go_director_inout %module(directors="1") go_director_inout
%include <std_string.i>
%{ %{
#include <string> #include <string>
%} %}
@ -108,6 +110,25 @@ type GoRetStruct struct {
$1.str.assign($input.p, $input.n); $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; %feature("director") MyClass;
%inline %inline
@ -121,6 +142,10 @@ class MyClass {
r.str = s.str; r.str = s.str;
return r; return r;
} }
virtual void S1(std::string s) = 0;
virtual void S2(std::string& s) = 0;
virtual void S3(std::string* s) = 0;
}; };
%} %}

View file

@ -453,9 +453,12 @@
%} %}
%typemap(freearg) %typemap(freearg)
char *, char *&, char[ANY], char[] char *, char[ANY], char[]
%{ free($1); %} %{ free($1); %}
%typemap(freearg) char *&
%{ free(*$1); %}
%typemap(out,fragment="AllocateString") %typemap(out,fragment="AllocateString")
char *, char *&, char[ANY], char[] char *, char *&, char[ANY], char[]
%{ $result = Swig_AllocateString((char*)$1, $1 ? strlen((char*)$1) : 0); %} %{ $result = Swig_AllocateString((char*)$1, $1 ? strlen((char*)$1) : 0); %}
@ -520,6 +523,44 @@
$2 = ($2_ltype)$input.n; $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 /* 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 we deliberately don't define them. The right thing would be to
capitalize the name. This is instead done in go.cxx. */ capitalize the name. This is instead done in go.cxx. */
@ -552,10 +593,7 @@
%typemap(godirectorin) enum SWIGTYPE & "" %typemap(godirectorin) enum SWIGTYPE & ""
%typemap(directorout) enum SWIGTYPE & %typemap(directorout) enum SWIGTYPE &
%{ %{ $result = $input; %}
$*1_ltype f = ($*1_ltype)*$input;
$result = ($1_ltype)&f;
%}
/* Arbitrary type. This is a type passed by value in the C/C++ code. /* 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 We convert it to a pointer for the Go code. Note that all basic

View file

@ -377,7 +377,7 @@ private:
/* --------------------------------------------------------------------- /* ---------------------------------------------------------------------
* top() * 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 * 1) A .c or .cxx file compiled with gcc. This file will contain
* function wrappers. Each wrapper will take a pointer to a * function wrappers. Each wrapper will take a pointer to a
@ -5284,7 +5284,7 @@ private:
* gcCTypeForGoValue() * gcCTypeForGoValue()
* *
* Given a type, return the C/C++ type which will be used to catch * 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) { String *gcCTypeForGoValue(Node *n, SwigType *type, String *name) {
@ -5293,7 +5293,19 @@ private:
String *tail = NewString(""); String *tail = NewString("");
SwigType *t = SwigType_typedef_resolve_all(type); 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) { while (Strncmp(gt, "*", 1) == 0) {
Replace(gt, "*", "", DOH_REPLACE_FIRST); Replace(gt, "*", "", DOH_REPLACE_FIRST);
Printv(tail, "*", NULL); Printv(tail, "*", NULL);
@ -5436,17 +5448,6 @@ private:
return ret; return ret;
} }
/* ----------------------------------------------------------------------
* 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 * goTypeIsInterface
* *