From e95ac8265154e1f3f9f05406c7f800182f1350b9 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 12 Dec 2013 07:59:47 +0000 Subject: [PATCH] Nested C class setters restored in c++out mode for Octave Suitable casts are required so that assignment of instances of nested classes work as the nested class is duplicated in the global namespace, eg: struct Outer { struct Nested { int bar; } bar_instance; }; Outer.bar_instance can now be assigned to. --- Examples/test-suite/nested_structs.i | 2 ++ .../test-suite/octave/nested_structs_runme.m | 14 +++++++++++++ Lib/typemaps/swigtype.swg | 6 +++--- Source/CParse/parser.y | 4 ++-- Source/Swig/cwrap.c | 21 ++++++++++++++++++- 5 files changed, 41 insertions(+), 6 deletions(-) create mode 100644 Examples/test-suite/octave/nested_structs_runme.m diff --git a/Examples/test-suite/nested_structs.i b/Examples/test-suite/nested_structs.i index add24ec17..459f25f00 100644 --- a/Examples/test-suite/nested_structs.i +++ b/Examples/test-suite/nested_structs.i @@ -23,6 +23,8 @@ void setValues(struct Outer *outer, int val) { outer->inside3 = &outer->inside2; outer->inside4[0].val = val * 4; } + +int getInside1Val(struct Outer *n) { return n->inside1.val; } %} /* diff --git a/Examples/test-suite/octave/nested_structs_runme.m b/Examples/test-suite/octave/nested_structs_runme.m new file mode 100644 index 000000000..a04aaa672 --- /dev/null +++ b/Examples/test-suite/octave/nested_structs_runme.m @@ -0,0 +1,14 @@ +nested_structs + +named = nested_structs.Named(); +named.val = 999; +assert(nested_structs.nestedByVal(named), 999); +assert(nested_structs.nestedByPtr(named), 999); + +outer = nested_structs.Outer(); +outer.inside1.val = 456; +assert(nested_structs.getInside1Val(outer), 456); + +outer.inside1 = named; +assert(nested_structs.getInside1Val(outer), 999); + diff --git a/Lib/typemaps/swigtype.swg b/Lib/typemaps/swigtype.swg index 5e92790d8..6c0affbe2 100644 --- a/Lib/typemaps/swigtype.swg +++ b/Lib/typemaps/swigtype.swg @@ -159,7 +159,7 @@ %typemap(memberin) SWIGTYPE [ANY] { if ($input) { size_t ii = 0; - for (; ii < (size_t)$1_dim0; ++ii) $1[ii] = $input[ii]; + for (; ii < (size_t)$1_dim0; ++ii) *($1_ltype)&$1[ii] = ($*1_ltype)$input[ii]; } else { %variable_nullref("$type","$name"); } @@ -168,7 +168,7 @@ %typemap(globalin) SWIGTYPE [ANY] { if ($input) { size_t ii = 0; - for (; ii < (size_t)$1_dim0; ++ii) $1[ii] = $input[ii]; + for (; ii < (size_t)$1_dim0; ++ii) *($1_ltype)&$1[ii] = ($*1_ltype)$input[ii]; } else { %variable_nullref("$type","$name"); } @@ -181,7 +181,7 @@ %variable_fail(res, "$type", "$name"); } else if (inp) { size_t ii = 0; - for (; ii < (size_t)$1_dim0; ++ii) $1[ii] = inp[ii]; + for (; ii < (size_t)$1_dim0; ++ii) *($1_ltype)&$1[ii] = ($*1_ltype)inp[ii]; } else { %variable_nullref("$type", "$name"); } diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index 0124ad25a..8e34833e2 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -3513,7 +3513,7 @@ cpp_class_decl : storage_class cpptype idcolon inherit LBRACE { while (p) { Setattr(p, "storage", $1); Setattr(p, "type" ,ty); - if (!cparse_cplusplus && currentOuterClass && (!Getattr(currentOuterClass, "name") || CPlusPlusOut)) { + if (!cparse_cplusplus && currentOuterClass && (!Getattr(currentOuterClass, "name"))) { SetFlag(p, "hasconsttype"); SetFlag(p, "feature:immutable"); } @@ -3674,7 +3674,7 @@ cpp_class_decl : storage_class cpptype idcolon inherit LBRACE { while (n) { Setattr(n,"storage",$1); Setattr(n, "type", ty); - if (!cparse_cplusplus && currentOuterClass && (!Getattr(currentOuterClass, "name") || CPlusPlusOut)) { + if (!cparse_cplusplus && currentOuterClass && (!Getattr(currentOuterClass, "name"))) { SetFlag(n,"hasconsttype"); SetFlag(n,"feature:immutable"); } diff --git a/Source/Swig/cwrap.c b/Source/Swig/cwrap.c index 6f8fa39e9..03020bb72 100644 --- a/Source/Swig/cwrap.c +++ b/Source/Swig/cwrap.c @@ -15,6 +15,7 @@ #include "swig.h" extern int cparse_cplusplus; +extern int CPlusPlusOut; static const char *cresult_variable_name = "result"; static Parm *nonvoid_parms(Parm *p) { @@ -775,7 +776,25 @@ String *Swig_cmemberset_call(const_String_or_char_ptr name, SwigType *type, Stri if (SwigType_type(type) != T_ARRAY) { if (!Strstr(type, "enum $unnamed")) { String *dref = Swig_wrapped_var_deref(type, pname1, varcref); - Printf(func, "if (%s) %s%s = %s", pname0, self, name, dref); + int extra_cast = 0; + if (CPlusPlusOut) { + /* Required for C nested structs compiled as C++ as a duplicate of the nested struct is put into the global namespace. + * We could improve this by adding the extra casts just for nested structs rather than all structs. */ + String *base = SwigType_base(type); + extra_cast = SwigType_isclass(base); + Delete(base); + } + if (extra_cast) { + String *lstr; + SwigType *ptype = Copy(type); + SwigType_add_pointer(ptype); + lstr = SwigType_lstr(ptype, 0); + Printf(func, "if (%s) *(%s)&%s%s = %s", pname0, lstr, self, name, dref); + Delete(lstr); + Delete(ptype); + } else { + Printf(func, "if (%s) %s%s = %s", pname0, self, name, dref); + } Delete(dref); } else { Printf(func, "if (%s && sizeof(int) == sizeof(%s%s)) *(int*)(void*)&(%s%s) = %s", pname0, self, name, self, name, pname1);