[Go] #2245 Handle NULL pointers for string* conversions.
Rearrange generation of director methods and rename receiver argument from p to swig_p. Fixes #2245
This commit is contained in:
parent
e1173cac26
commit
87cbf8c341
5 changed files with 194 additions and 162 deletions
|
|
@ -7,6 +7,11 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/
|
|||
Version 4.1.0 (in progress)
|
||||
===========================
|
||||
|
||||
2022-07-05: ianlancetaylor
|
||||
[Go] #2245 Handle NULL pointers for string* conversions.
|
||||
Rearrange generation of director methods and rename
|
||||
receiver argument from p to swig_p.
|
||||
|
||||
2022-07-03: wsfulton
|
||||
Performane optimisation for directors for classes passed by value. The directorin
|
||||
typemaps in the director methods now use std::move on the input parameter when
|
||||
|
|
|
|||
|
|
@ -67,6 +67,9 @@ func main() {
|
|||
|
||||
a.CallS4([]string{ "T1", "T2" })
|
||||
|
||||
a.S5(&str)
|
||||
a.S5(nil)
|
||||
|
||||
a = wrap.NewDirectorMyClass(nil)
|
||||
s = a.Adjust(m)
|
||||
if s.Str != `{"first":"second"}` {
|
||||
|
|
|
|||
|
|
@ -225,6 +225,7 @@ class MyClass {
|
|||
virtual void S2(std::string& s) = 0;
|
||||
virtual void S3(std::string* s) = 0;
|
||||
virtual void S4(const char * const *strarray);
|
||||
virtual int S5(const std::string* s);
|
||||
};
|
||||
|
||||
void MyClass::S1(std::string s) {
|
||||
|
|
@ -239,4 +240,12 @@ void MyClass::CallS4(const char * const *strarray) {
|
|||
this->S4(strarray);
|
||||
}
|
||||
|
||||
int MyClass::S5(const std::string* s) {
|
||||
if (s) {
|
||||
return (*s)[0];
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
%}
|
||||
|
|
|
|||
|
|
@ -93,17 +93,22 @@ class string;
|
|||
|
||||
%typemap(in) string * (string temp)
|
||||
%{
|
||||
temp.assign($input->p, $input->n);
|
||||
$1 = &temp;
|
||||
if ($input) {
|
||||
temp.assign($input->p, $input->n);
|
||||
$1 = &temp;
|
||||
} else
|
||||
$1 = 0;
|
||||
%}
|
||||
|
||||
%typemap(godirectorout) string *
|
||||
%{
|
||||
{
|
||||
if $input != nil {
|
||||
p := Swig_malloc(len(*$input))
|
||||
s := (*[1<<30]byte)(unsafe.Pointer(p))[:len(*$input)]
|
||||
copy(s, *$input)
|
||||
$result = (*string)(unsafe.Pointer(&s))
|
||||
} else {
|
||||
$result = nil
|
||||
}
|
||||
%}
|
||||
|
||||
|
|
@ -125,17 +130,27 @@ class string;
|
|||
|
||||
%typemap(directorin,fragment="AllocateString") string * (_gostring_ temp)
|
||||
%{
|
||||
temp = Swig_AllocateString($1->data(), $1->length());
|
||||
$input = &temp;
|
||||
if ($1) {
|
||||
temp = Swig_AllocateString($1->data(), $1->length());
|
||||
$input = &temp;
|
||||
} else
|
||||
$input = 0;
|
||||
%}
|
||||
|
||||
%typemap(godirectorin,fragment="CopyString") string *
|
||||
%{ *$result = swigCopyString(*$input); %}
|
||||
|
||||
%typemap(argout,fragment="AllocateString") string *
|
||||
%{ *$input = Swig_AllocateString($1->data(), $1->length()); %}
|
||||
%{
|
||||
if ($1)
|
||||
*$input = Swig_AllocateString($1->data(), $1->length());
|
||||
%}
|
||||
|
||||
%typemap(goargout,fragment="CopyString") string *
|
||||
%{ *$input = swigCopyString(*$1) %}
|
||||
%{
|
||||
if $input != nil {
|
||||
*$1 = swigCopyString(*$input)
|
||||
}
|
||||
%}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3580,11 +3580,162 @@ private:
|
|||
|
||||
Printv(f_go_wrappers, "}\n\n", NULL);
|
||||
|
||||
// Define a method in the C++ director class that the C++ upcall
|
||||
// function can call. This permits an upcall to a protected
|
||||
// method.
|
||||
|
||||
if (!GetFlag(n, "abstract")) {
|
||||
// Define a function that uses the Go director type that other
|
||||
// methods in the Go type can call to get parent methods.
|
||||
|
||||
Printv(f_go_wrappers, "func Director", cn, go_with_over_name, "(swig_p ", cn, NULL);
|
||||
|
||||
p = parms;
|
||||
for (int i = 0; i < parm_count; ++i) {
|
||||
p = getParm(p);
|
||||
Printv(f_go_wrappers, ", ", Getattr(p, "lname"), " ", NULL);
|
||||
String *tm = goType(p, Getattr(p, "type"));
|
||||
Printv(f_go_wrappers, tm, NULL);
|
||||
Delete(tm);
|
||||
p = nextParm(p);
|
||||
}
|
||||
|
||||
Printv(f_go_wrappers, ")", NULL);
|
||||
|
||||
if (SwigType_type(result) != T_VOID) {
|
||||
String *tm = goType(n, result);
|
||||
Printv(f_go_wrappers, " ", tm, NULL);
|
||||
Delete(tm);
|
||||
}
|
||||
|
||||
Printv(f_go_wrappers, " {\n", NULL);
|
||||
|
||||
String *ret_type = NULL;
|
||||
bool memcpy_ret = false;
|
||||
String *wt = NULL;
|
||||
String *goout = NULL;
|
||||
if (SwigType_type(result) != T_VOID) {
|
||||
ret_type = goImType(n, result);
|
||||
Printv(f_go_wrappers, "\tvar swig_r ", ret_type, "\n", NULL);
|
||||
goout = goTypemapLookup("goout", n, "swig_r");
|
||||
|
||||
bool c_struct_type;
|
||||
Delete(cgoTypeForGoValue(n, result, &c_struct_type));
|
||||
if (c_struct_type) {
|
||||
memcpy_ret = true;
|
||||
}
|
||||
}
|
||||
|
||||
String *call = NewString("");
|
||||
|
||||
Printv(call, "\t", NULL);
|
||||
if (SwigType_type(result) != T_VOID) {
|
||||
if (memcpy_ret) {
|
||||
Printv(call, "swig_r_p := ", NULL);
|
||||
} else {
|
||||
Printv(call, "swig_r = (", ret_type, ")(", NULL);
|
||||
}
|
||||
if (goTypeIsInterface(n, result)) {
|
||||
wt = goWrapperType(n, result, true);
|
||||
Printv(call, "(", wt, ")(", NULL);
|
||||
}
|
||||
}
|
||||
|
||||
Printv(call, "C.", upcall_wname, "(C.uintptr_t(swig_p.(*",
|
||||
director_struct_name, ").", go_type_name, ")", NULL);
|
||||
|
||||
p = parms;
|
||||
for (int i = 0; i < parm_count; ++i) {
|
||||
Printv(call, ", ", NULL);
|
||||
p = getParm(p);
|
||||
SwigType *pt = Getattr(p, "type");
|
||||
|
||||
String *ivar = NewStringf("_swig_i_%d", i);
|
||||
|
||||
String *ln = Copy(Getattr(p, "lname"));
|
||||
|
||||
String *goin = goGetattr(p, "tmap:goin");
|
||||
if (goin == NULL) {
|
||||
Printv(f_go_wrappers, "\t", ivar, " := ", NULL);
|
||||
bool need_close = false;
|
||||
if (goTypeIsInterface(p, pt)) {
|
||||
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 {
|
||||
String *itm = goImType(p, pt);
|
||||
Printv(f_go_wrappers, "\tvar ", ivar, " ", itm, "\n", NULL);
|
||||
goin = Copy(goin);
|
||||
Replaceall(goin, "$input", ln);
|
||||
Replaceall(goin, "$result", ivar);
|
||||
Printv(f_go_wrappers, goin, "\n", NULL);
|
||||
Delete(goin);
|
||||
}
|
||||
|
||||
Setattr(p, "emit:goinput", ivar);
|
||||
|
||||
bool c_struct_type;
|
||||
String *ct = cgoTypeForGoValue(p, pt, &c_struct_type);
|
||||
if (c_struct_type) {
|
||||
Printv(call, "*(*C.", ct, ")(unsafe.Pointer(&", ivar, "))", NULL);
|
||||
} else {
|
||||
Printv(call, "C.", ct, "(", ivar, ")", NULL);
|
||||
}
|
||||
|
||||
Delete(ln);
|
||||
|
||||
p = nextParm(p);
|
||||
}
|
||||
|
||||
Printv(call, ")", NULL);
|
||||
|
||||
if (wt) {
|
||||
// Close the type conversion to the wrapper type.
|
||||
Printv(call, ")", NULL);
|
||||
}
|
||||
if (SwigType_type(result) != T_VOID && !memcpy_ret) {
|
||||
// Close the type conversion of the return value.
|
||||
Printv(call, ")", NULL);
|
||||
}
|
||||
|
||||
Printv(call, "\n", NULL);
|
||||
|
||||
Printv(f_go_wrappers, call, NULL);
|
||||
Delete(call);
|
||||
|
||||
if (memcpy_ret) {
|
||||
Printv(f_go_wrappers, "\tswig_r = *(*", ret_type, ")(unsafe.Pointer(&swig_r_p))\n", NULL);
|
||||
}
|
||||
|
||||
goargout(parms);
|
||||
|
||||
if (SwigType_type(result) != T_VOID) {
|
||||
if (goout == NULL) {
|
||||
Printv(f_go_wrappers, "\treturn swig_r\n", NULL);
|
||||
} else {
|
||||
String *tm = goType(n, result);
|
||||
Printv(f_go_wrappers, "\tvar swig_r_1 ", tm, "\n", NULL);
|
||||
Replaceall(goout, "$input", "swig_r");
|
||||
Replaceall(goout, "$result", "swig_r_1");
|
||||
Printv(f_go_wrappers, goout, "\n", NULL);
|
||||
Printv(f_go_wrappers, "\treturn swig_r_1\n", NULL);
|
||||
}
|
||||
}
|
||||
|
||||
Printv(f_go_wrappers, "}\n\n", NULL);
|
||||
|
||||
if (ret_type) {
|
||||
Delete(ret_type);
|
||||
}
|
||||
if (wt) {
|
||||
Delete(wt);
|
||||
}
|
||||
|
||||
// Define a method in the C++ director class that the C++
|
||||
// upcall function can call. This permits an upcall to a
|
||||
// protected method.
|
||||
|
||||
String *upcall_method_name = NewString("_swig_upcall_");
|
||||
Append(upcall_method_name, name);
|
||||
if (overname) {
|
||||
|
|
@ -3683,157 +3834,6 @@ private:
|
|||
|
||||
Swig_restore(n);
|
||||
Delete(upcall_method_name);
|
||||
|
||||
// Define a function that uses the Go director type that other
|
||||
// methods in the Go type can call to get parent methods.
|
||||
|
||||
Printv(f_go_wrappers, "func Director", cn, go_with_over_name, "(p ", cn, NULL);
|
||||
|
||||
p = parms;
|
||||
for (int i = 0; i < parm_count; ++i) {
|
||||
p = getParm(p);
|
||||
Printv(f_go_wrappers, ", ", Getattr(p, "lname"), " ", NULL);
|
||||
String *tm = goType(p, Getattr(p, "type"));
|
||||
Printv(f_go_wrappers, tm, NULL);
|
||||
Delete(tm);
|
||||
p = nextParm(p);
|
||||
}
|
||||
|
||||
Printv(f_go_wrappers, ")", NULL);
|
||||
|
||||
if (SwigType_type(result) != T_VOID) {
|
||||
String *tm = goType(n, result);
|
||||
Printv(f_go_wrappers, " ", tm, NULL);
|
||||
Delete(tm);
|
||||
}
|
||||
|
||||
Printv(f_go_wrappers, " {\n", NULL);
|
||||
|
||||
String *ret_type = NULL;
|
||||
bool memcpy_ret = false;
|
||||
String *wt = NULL;
|
||||
String *goout = NULL;
|
||||
if (SwigType_type(result) != T_VOID) {
|
||||
ret_type = goImType(n, result);
|
||||
Printv(f_go_wrappers, "\tvar swig_r ", ret_type, "\n", NULL);
|
||||
goout = goTypemapLookup("goout", n, "swig_r");
|
||||
|
||||
bool c_struct_type;
|
||||
Delete(cgoTypeForGoValue(n, result, &c_struct_type));
|
||||
if (c_struct_type) {
|
||||
memcpy_ret = true;
|
||||
}
|
||||
}
|
||||
|
||||
String *call = NewString("");
|
||||
|
||||
Printv(call, "\t", NULL);
|
||||
if (SwigType_type(result) != T_VOID) {
|
||||
if (memcpy_ret) {
|
||||
Printv(call, "swig_r_p := ", NULL);
|
||||
} else {
|
||||
Printv(call, "swig_r = (", ret_type, ")(", NULL);
|
||||
}
|
||||
if (goTypeIsInterface(n, result)) {
|
||||
wt = goWrapperType(n, result, true);
|
||||
Printv(call, "(", wt, ")(", NULL);
|
||||
}
|
||||
}
|
||||
|
||||
Printv(call, "C.", upcall_wname, "(C.uintptr_t(p.(*",
|
||||
director_struct_name, ").", go_type_name, ")", NULL);
|
||||
|
||||
p = parms;
|
||||
for (int i = 0; i < parm_count; ++i) {
|
||||
Printv(call, ", ", NULL);
|
||||
p = getParm(p);
|
||||
SwigType *pt = Getattr(p, "type");
|
||||
|
||||
String *ivar = NewStringf("_swig_i_%d", i);
|
||||
|
||||
String *ln = Copy(Getattr(p, "lname"));
|
||||
|
||||
String *goin = goGetattr(p, "tmap:goin");
|
||||
if (goin == NULL) {
|
||||
Printv(f_go_wrappers, "\t", ivar, " := ", NULL);
|
||||
bool need_close = false;
|
||||
if (goTypeIsInterface(p, pt)) {
|
||||
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 {
|
||||
String *itm = goImType(p, pt);
|
||||
Printv(f_go_wrappers, "\tvar ", ivar, " ", itm, "\n", NULL);
|
||||
goin = Copy(goin);
|
||||
Replaceall(goin, "$input", ln);
|
||||
Replaceall(goin, "$result", ivar);
|
||||
Printv(f_go_wrappers, goin, "\n", NULL);
|
||||
Delete(goin);
|
||||
}
|
||||
|
||||
Setattr(p, "emit:goinput", ivar);
|
||||
|
||||
bool c_struct_type;
|
||||
String *ct = cgoTypeForGoValue(p, pt, &c_struct_type);
|
||||
if (c_struct_type) {
|
||||
Printv(call, "*(*C.", ct, ")(unsafe.Pointer(&", ivar, "))", NULL);
|
||||
} else {
|
||||
Printv(call, "C.", ct, "(", ivar, ")", NULL);
|
||||
}
|
||||
|
||||
Delete(ln);
|
||||
|
||||
p = nextParm(p);
|
||||
}
|
||||
|
||||
Printv(call, ")", NULL);
|
||||
|
||||
if (wt) {
|
||||
// Close the type conversion to the wrapper type.
|
||||
Printv(call, ")", NULL);
|
||||
}
|
||||
if (SwigType_type(result) != T_VOID && !memcpy_ret) {
|
||||
// Close the type conversion of the return value.
|
||||
Printv(call, ")", NULL);
|
||||
}
|
||||
|
||||
Printv(call, "\n", NULL);
|
||||
|
||||
Printv(f_go_wrappers, call, NULL);
|
||||
Delete(call);
|
||||
|
||||
if (memcpy_ret) {
|
||||
Printv(f_go_wrappers, "\tswig_r = *(*", ret_type, ")(unsafe.Pointer(&swig_r_p))\n", NULL);
|
||||
}
|
||||
|
||||
goargout(parms);
|
||||
|
||||
if (SwigType_type(result) != T_VOID) {
|
||||
if (goout == NULL) {
|
||||
Printv(f_go_wrappers, "\treturn swig_r\n", NULL);
|
||||
} else {
|
||||
String *tm = goType(n, result);
|
||||
Printv(f_go_wrappers, "\tvar swig_r_1 ", tm, "\n", NULL);
|
||||
Replaceall(goout, "$input", "swig_r");
|
||||
Replaceall(goout, "$result", "swig_r_1");
|
||||
Printv(f_go_wrappers, goout, "\n", NULL);
|
||||
Printv(f_go_wrappers, "\treturn swig_r_1\n", NULL);
|
||||
}
|
||||
}
|
||||
|
||||
Printv(f_go_wrappers, "}\n\n", NULL);
|
||||
|
||||
if (ret_type) {
|
||||
Delete(ret_type);
|
||||
}
|
||||
if (wt) {
|
||||
Delete(wt);
|
||||
}
|
||||
}
|
||||
|
||||
// The Go function which invokes the method. This is called by
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue