[Go] Make sure that arguments for which use memcpy when calling C are
still live after the call. This ensures that they will not be collected if the GC runs during the call.
This commit is contained in:
parent
140782054a
commit
48263f4802
4 changed files with 77 additions and 34 deletions
|
|
@ -44,14 +44,14 @@ type GoRetStruct struct {
|
||||||
$result.str.assign($input.p, $input.n);
|
$result.str.assign($input.p, $input.n);
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%typemap(out) RetStruct
|
%typemap(out,fragment="AllocateString") RetStruct
|
||||||
%{
|
%{
|
||||||
$result = _swig_makegostring($1.str.data(), $1.str.length());
|
$result = Swig_AllocateString($1.str.data(), $1.str.length());
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%typemap(goout) RetStruct
|
%typemap(goout,fragment="CopyString") RetStruct
|
||||||
%{
|
%{
|
||||||
$result = GoRetStruct{Str: $input}
|
$result = GoRetStruct{Str: swigCopyString($input)}
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%typemap(godirectorout) RetStruct
|
%typemap(godirectorout) RetStruct
|
||||||
|
|
@ -81,23 +81,28 @@ type GoRetStruct struct {
|
||||||
}
|
}
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%typemap(directorin) MyStruct
|
%typemap(directorin,fragment="AllocateString") MyStruct
|
||||||
%{
|
%{
|
||||||
$input = _swig_makegostring($1.str.data(), $1.str.length());
|
$input = Swig_AllocateString($1.str.data(), $1.str.length());
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%typemap(out) MyStruct
|
%typemap(godirectorin,fragment="CopyString") MyStruct
|
||||||
%{
|
%{
|
||||||
$result = _swig_makegostring($1.str.data(), $1.str.length());
|
if err := json.Unmarshal([]byte(swigCopyString($input)), &$result); err != nil {
|
||||||
%}
|
|
||||||
|
|
||||||
%typemap(godirectorin) MyStruct
|
|
||||||
%{
|
|
||||||
if err := json.Unmarshal([]byte($input), &$result); err != nil {
|
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
%typemap(out,fragment="AllocateString") MyStruct
|
||||||
|
%{
|
||||||
|
$result = Swig_AllocateString($1.str.data(), $1.str.length());
|
||||||
|
%}
|
||||||
|
|
||||||
|
%typemap(goout,fragment="CopyString") MyStruct
|
||||||
|
%{
|
||||||
|
$result = swigCopyString($input)
|
||||||
|
%}
|
||||||
|
|
||||||
%typemap(in) MyStruct
|
%typemap(in) MyStruct
|
||||||
%{
|
%{
|
||||||
$1.str.assign($input.p, $input.n);
|
$1.str.assign($input.p, $input.n);
|
||||||
|
|
|
||||||
|
|
@ -56,14 +56,14 @@ type In json.Marshaler
|
||||||
|
|
||||||
%typemap(imtype) RetStruct "string"
|
%typemap(imtype) RetStruct "string"
|
||||||
|
|
||||||
%typemap(out) RetStruct
|
%typemap(out,fragment="AllocateString") RetStruct
|
||||||
%{
|
%{
|
||||||
$result = _swig_makegostring($1.str.data(), $1.str.length());
|
$result = Swig_AllocateString($1.str.data(), $1.str.length());
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%typemap(goout) RetStruct
|
%typemap(goout,fragment="CopyString") RetStruct
|
||||||
%{
|
%{
|
||||||
if err := json.Unmarshal([]byte($1), &$result); err != nil {
|
if err := json.Unmarshal([]byte(swigCopyString($1)), &$result); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
%}
|
%}
|
||||||
|
|
@ -146,7 +146,7 @@ static void putuint64(std::string *s, size_t off, uint64_t v) {
|
||||||
%}
|
%}
|
||||||
|
|
||||||
// Pack the vector into a string.
|
// Pack the vector into a string.
|
||||||
%typemap(argout) MyArray*
|
%typemap(argout,fragment="AllocateString") MyArray*
|
||||||
%{
|
%{
|
||||||
{
|
{
|
||||||
size_t tot = 8;
|
size_t tot = 8;
|
||||||
|
|
@ -164,15 +164,15 @@ static void putuint64(std::string *s, size_t off, uint64_t v) {
|
||||||
str.replace(off, p->size(), *p);
|
str.replace(off, p->size(), *p);
|
||||||
off += p->size();
|
off += p->size();
|
||||||
}
|
}
|
||||||
*$input = _swig_makegostring(str.data(), str.size());
|
*$input = Swig_AllocateString(str.data(), str.size());
|
||||||
}
|
}
|
||||||
%}
|
%}
|
||||||
|
|
||||||
// Unpack the string into a []string.
|
// Unpack the string into a []string.
|
||||||
%typemap(goargout) MyArray*
|
%typemap(goargout,fragment="CopyString") MyArray*
|
||||||
%{
|
%{
|
||||||
{
|
{
|
||||||
str := *$input
|
str := swigCopyString(*$input)
|
||||||
bin := binary.LittleEndian
|
bin := binary.LittleEndian
|
||||||
size := bin.Uint64([]byte(str[:8]))
|
size := bin.Uint64([]byte(str[:8]))
|
||||||
str = str[8:]
|
str = str[8:]
|
||||||
|
|
|
||||||
|
|
@ -113,8 +113,22 @@ static char *_swig_topofstack() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _swig_gopanic(const char *p) {
|
||||||
|
struct {
|
||||||
|
const char *p;
|
||||||
|
} a;
|
||||||
|
a.p = p;
|
||||||
|
crosscall2(_cgo_panic, &a, (int) sizeof a);
|
||||||
|
}
|
||||||
|
|
||||||
|
%}
|
||||||
|
|
||||||
|
#if !SWIGGO_CGO
|
||||||
|
|
||||||
/* This is here for backward compatibility, but it will not work
|
/* This is here for backward compatibility, but it will not work
|
||||||
with Go 1.5 or later. Do not use it in new code. */
|
with Go 1.5 or later. Do not use it in new code. */
|
||||||
|
%insert(runtime) %{
|
||||||
|
|
||||||
static void *_swig_goallocate(size_t len) {
|
static void *_swig_goallocate(size_t len) {
|
||||||
struct {
|
struct {
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
@ -125,16 +139,10 @@ static void *_swig_goallocate(size_t len) {
|
||||||
return a.ret;
|
return a.ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _swig_gopanic(const char *p) {
|
|
||||||
struct {
|
|
||||||
const char *p;
|
|
||||||
} a;
|
|
||||||
a.p = p;
|
|
||||||
crosscall2(_cgo_panic, &a, (int) sizeof a);
|
|
||||||
}
|
|
||||||
|
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !SWIGGO_CGO
|
#if !SWIGGO_CGO
|
||||||
|
|
||||||
/* Boilerplate for C code when using 6g/8g. This code is compiled
|
/* Boilerplate for C code when using 6g/8g. This code is compiled
|
||||||
|
|
@ -246,6 +254,8 @@ void SwigCgocallBackDone() {
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if !SWIGGO_CGO
|
||||||
|
|
||||||
%insert(runtime) %{
|
%insert(runtime) %{
|
||||||
|
|
||||||
/* This is here for backward compatibility, but it will not work
|
/* This is here for backward compatibility, but it will not work
|
||||||
|
|
@ -258,6 +268,12 @@ static _gostring_ _swig_makegostring(const char *p, size_t l) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
%}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
%insert(runtime) %{
|
||||||
|
|
||||||
#define SWIG_contract_assert(expr, msg) \
|
#define SWIG_contract_assert(expr, msg) \
|
||||||
if (!(expr)) { _swig_gopanic(msg); } else
|
if (!(expr)) { _swig_gopanic(msg); } else
|
||||||
%}
|
%}
|
||||||
|
|
@ -290,8 +306,6 @@ type _ unsafe.Pointer
|
||||||
|
|
||||||
%}
|
%}
|
||||||
|
|
||||||
#if !SWIGGO_CGO
|
|
||||||
|
|
||||||
/* Swig_always_false is used to conditionally assign parameters to
|
/* Swig_always_false is used to conditionally assign parameters to
|
||||||
Swig_escape_val so that the compiler thinks that they escape. We
|
Swig_escape_val so that the compiler thinks that they escape. We
|
||||||
only assign them if Swig_always_false is true, which it never is.
|
only assign them if Swig_always_false is true, which it never is.
|
||||||
|
|
@ -302,8 +316,6 @@ var Swig_escape_always_false bool
|
||||||
var Swig_escape_val interface{}
|
var Swig_escape_val interface{}
|
||||||
%}
|
%}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Function pointers are translated by the code in go.cxx into
|
/* Function pointers are translated by the code in go.cxx into
|
||||||
_swig_fnptr. Member pointers are translated to _swig_memberptr. */
|
_swig_fnptr. Member pointers are translated to _swig_memberptr. */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2035,7 +2035,7 @@ private:
|
||||||
* needs to explicitly escape. This is true if the parameter has a
|
* needs to explicitly escape. This is true if the parameter has a
|
||||||
* non-empty argout or freearg typemap, because in those cases the
|
* non-empty argout or freearg typemap, because in those cases the
|
||||||
* Go argument might be or contain a pointer. We need to ensure
|
* Go argument might be or contain a pointer. We need to ensure
|
||||||
* that that pointer does not oint into the stack, which means that
|
* that that pointer does not point into the stack, which means that
|
||||||
* it needs to escape.
|
* it needs to escape.
|
||||||
* ---------------------------------------------------------------------- */
|
* ---------------------------------------------------------------------- */
|
||||||
bool paramNeedsEscape(Parm *p) {
|
bool paramNeedsEscape(Parm *p) {
|
||||||
|
|
@ -2502,6 +2502,28 @@ private:
|
||||||
p = Getattr(p, "tmap:goargout:next");
|
p = Getattr(p, "tmap:goargout:next");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// When using cgo, if we need to memcpy a parameter to pass it to
|
||||||
|
// the C code, the compiler may think that the parameter is not
|
||||||
|
// live during the function call. If the garbage collector runs
|
||||||
|
// while the C/C++ function is running, the parameter may be
|
||||||
|
// freed. Force the compiler to see the parameter as live across
|
||||||
|
// the C/C++ function.
|
||||||
|
if (cgo_flag) {
|
||||||
|
int parm_count = emit_num_arguments(parms);
|
||||||
|
p = parms;
|
||||||
|
for (int i = 0; i < parm_count; ++i) {
|
||||||
|
p = getParm(p);
|
||||||
|
bool c_struct_type;
|
||||||
|
Delete(cgoTypeForGoValue(p, Getattr(p, "type"), &c_struct_type));
|
||||||
|
if (c_struct_type) {
|
||||||
|
Printv(f_go_wrappers, "\tif Swig_escape_always_false {\n", NULL);
|
||||||
|
Printv(f_go_wrappers, "\t\tSwig_escape_val = ", Getattr(p, "emit:goinput"), "\n", NULL);
|
||||||
|
Printv(f_go_wrappers, "\t}\n", NULL);
|
||||||
|
}
|
||||||
|
p = nextParm(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -----------------------------------------------------------------------
|
/* -----------------------------------------------------------------------
|
||||||
|
|
@ -3537,6 +3559,8 @@ private:
|
||||||
DelWrapper(dummy);
|
DelWrapper(dummy);
|
||||||
|
|
||||||
Swig_typemap_attach_parms("gotype", parms, NULL);
|
Swig_typemap_attach_parms("gotype", parms, NULL);
|
||||||
|
Swig_typemap_attach_parms("goin", parms, NULL);
|
||||||
|
Swig_typemap_attach_parms("goargout", parms, NULL);
|
||||||
Swig_typemap_attach_parms("imtype", parms, NULL);
|
Swig_typemap_attach_parms("imtype", parms, NULL);
|
||||||
int parm_count = emit_num_arguments(parms);
|
int parm_count = emit_num_arguments(parms);
|
||||||
|
|
||||||
|
|
@ -3689,6 +3713,8 @@ private:
|
||||||
|
|
||||||
Printv(f_go_wrappers, call, "\n", NULL);
|
Printv(f_go_wrappers, call, "\n", NULL);
|
||||||
|
|
||||||
|
goargout(parms);
|
||||||
|
|
||||||
Printv(f_go_wrappers, "\treturn p\n", NULL);
|
Printv(f_go_wrappers, "\treturn p\n", NULL);
|
||||||
Printv(f_go_wrappers, "}\n\n", NULL);
|
Printv(f_go_wrappers, "}\n\n", NULL);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue