Patch #1797133 from David Piepgrass fixes %attribute when the getter has the same name as the attribute name and no longer generate non-functional setter for read-only attributes.

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@9990 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
William S Fulton 2007-10-15 21:57:51 +00:00
commit acb5bde28c
3 changed files with 131 additions and 82 deletions

View file

@ -1,11 +1,26 @@
Version 1.3.32 (in progress) Version 1.3.32 (in progress)
============================ ============================
10/15/2007: wsfulton
Patch #1797133 from David Piepgrass fixes %attribute when the getter has the same name
as the attribute name and no longer generate non-functional setter for read-only attributes.
10/15/2007: olly 10/15/2007: olly
[Tcl] Prevent SWIG_Tcl_ConvertPtr from calling the unknown proc. [Tcl] Prevent SWIG_Tcl_ConvertPtr from calling the unknown proc.
Add Examples/tcl/std_vector/ which this change fixes. Patch Add Examples/tcl/std_vector/ which this change fixes. Patch
is from "Cliff C" in SF#1809819. is from "Cliff C" in SF#1809819.
10/12/2007: wsfulton
[Java] Add DetachCurrentThread back in for directors. See entry dated 08/11/2006 and
search for DetachCurrentThread on the mailing lists for details. The crashes on Solaris
seem to be only present in jdk-1.4.2 and lower (jdk-1.5.0 and jdk-1.6.0 are okay), so
anyone using directors should use a recent jdk on Solaris, or define (see director.swg)
SWIG_JAVA_NO_DETACH_CURRENT_THREAD to the C++ compiler to get old behaviour.
10/12/2007: wsfulton
[Java] Ensure the premature garbage collection prevention parameter (pgcpp) is generated
when there are C comments in the jtype and jstype typemaps.
10/12/2007: wuzzeb 10/12/2007: wuzzeb
Added a testsuite entry for Bug #1735931 Added a testsuite entry for Bug #1735931
@ -150,7 +165,7 @@ Version 1.3.32 (in progress)
[PHP5] Generate __isset() methods for setters for PHP 5.1 and later. [PHP5] Generate __isset() methods for setters for PHP 5.1 and later.
08/20/2007: wsfulton 08/20/2007: wsfulton
[Java C#] Fix director bug #1776651 reported by Stephae Routelous which occurred when [Java C#] Fix director bug #1776651 reported by Stephane Routelous which occurred when
the director class name is the same as the start of some other symbols used within the director class name is the same as the start of some other symbols used within
the director class. the director class.

View file

@ -1,7 +1,14 @@
%module li_attribute %module li_attribute
%include exception.i %include <exception.i>
%include attribute.i
//#define SWIG_ATTRIBUTE_TEMPLATE
%include <attribute.i>
%{
// forward reference needed if using SWIG_ATTRIBUTE_TEMPLATE
class A;
%}
%attribute(A, int, a, get_a, set_a); %attribute(A, int, a, get_a, set_a);
%attribute_ref(A, int, b); %attribute_ref(A, int, b);

View file

@ -27,7 +27,6 @@
%attribute(A, int, c, get_c); %attribute(A, int, c, get_c);
Use %attribute_ref when you have const/non-const reference Use %attribute_ref when you have const/non-const reference
access methods, like in: access methods, like in:
@ -51,9 +50,12 @@
%attribute_ref(class, type, refname, attr); %attribute_ref(class, type, refname, attr);
if the internal C++ reference methods have a different name from the if the internal C++ reference methods have a different name from the
attribute you want. attribute you want. There's an inconsistency here (retained for
compatibility): when using %attribute_ref, the C++ symbol name comes
before the attribute name, but when you use %attribute, the attribute
name comes before the C++ symbol names.
Then you can use the instances like: Now you can use the attributes like so:
x = A() x = A()
x.a = 3 # calls A::set_a x.a = 3 # calls A::set_a
@ -62,102 +64,127 @@
x.b = 3 # calls A::b() x.b = 3 # calls A::b()
print x.b # calls A::b() const print x.b # calls A::b() const
NOTE: remember that if the type contains commas, such as Use %attribute2 instead of %attribute to indicate that reference-pointer
'std::pair<int,int>', you need to use the macro like: translation is required. You use %attribute2 instead of %attribute in
cases like this:
%attribute2(MyClass, MyFoo, Foo, GetFoo, SetFoo);
%inline %{
struct MyFoo {
int x;
};
class MyClass {
MyFoo foo;
public:
MyFoo& GetFoo() { return foo; }
void SetFoo(const MyFoo& other) { foo = other; }
};
%}
Here, the data type of the property is a wrapped type (MyFoo) and on the
C++ side it is passed by reference. The problem is that the SWIG wrapper will
pass around a pointer (MyFoo *) which is not compatible with the reference
type of the accessors (MyFoo &). Therefore, if you use %attribute, you'll get
an error from your C/C++ compiler. %attribute2 translates between a pointer
and a reference to eliminate the error. In case you're confused, I'll make it
simple: just use %attribute at first, but if the C/C++ compiler gives an error
while compiling the wrapper, try %attribute2 instead.
NOTE: remember that if the type contains commas, such as 'std::pair<int,int>',
you need to use the macro like:
%attribute_ref(A, %arg(std::pair<int,int>), pval); %attribute_ref(A, %arg(std::pair<int,int>), pval);
where %arg() 'normalize' the type to be understood as a single where %arg() 'normalizes' the type to be understood as a single
argument, otherwise the macro will get confused (see the 'cpp' argument, otherwise the macro will get confused by the comma (see the
documentation). 'cpp' documentation).
*/ */
#ifndef %attribute_exception
#define %attribute_exception(code,msg) SWIG_exception_fail(code,msg)
#endif
// //
// Define SWIG_ATTRIBUTE_TEMPLATE if you want to use templates. // Define SWIG_ATTRIBUTE_TEMPLATE if you want to use templates instead of macros for the C++ get and set wrapper methods
// //
//#define SWIG_ATTRIBUTE_TEMPLATE //#define SWIG_ATTRIBUTE_TEMPLATE
%define %attribute_custom(Class, AttributeType, AttributeName, GetMethod, SetMethod, GetMethodCall, SetMethodCall)
%ignore Class::GetMethod();
%ignore Class::GetMethod() const;
#if #SetMethod != #AttributeName
%ignore Class::SetMethod;
#endif
%extend Class {
AttributeType AttributeName;
}
#if defined(__cplusplus) && defined(SWIG_ATTRIBUTE_TEMPLATE) #if defined(__cplusplus) && defined(SWIG_ATTRIBUTE_TEMPLATE)
%define %_attribute(Class, Wrap, type, attr, getcode, setcode) %{
%extend Class { template < class C > inline AttributeType %mangle(Class) ##_## AttributeName ## _get(const C* self_) {
type attr; return GetMethodCall;
} }
%{ template < class C > inline AttributeType %mangle(Class) ##_## AttributeName ## _get(C* self_) {
template <class C> inline return GetMethodCall;
type Wrap ##_## attr ## _get(const C* _t) }
{ return getcode; } template < class C > inline void %mangle(Class) ##_## AttributeName ## _set(C* self_, AttributeType val_) {
SetMethodCall;
template <class C> inline }
type Wrap ##_## attr ## _get(C* _t) %}
{ return getcode; }
template <class C> inline
void Wrap ##_## attr ## _set(C* _t, type _val)
{ setcode; }
%}
%enddef
#else #else
%{
%define %_attribute(Class, Wrap, type, attr, getcode, setcode) #define %mangle(Class) ##_## AttributeName ## _get(self_) GetMethodCall
%extend Class { #define %mangle(Class) ##_## AttributeName ## _set(self_, val_) SetMethodCall
type attr; %}
}
%{
#define Wrap ##_## attr ## _get(_t) getcode
#define Wrap ##_## attr ## _set(_t, _val) setcode
%}
%enddef
#endif
//
// Internal versions, need Wrap name
//
%define %attribute_T(Class, Wrap, type, attr, get, set...)
%ignore Class::get;
#if #set != ""
%ignore Class::set;
%_attribute(%arg(Class), Wrap, %arg(type),
attr, _t->get(), _t->set(_val))
#else
%_attribute(%arg(Class), Wrap, %arg(type),
attr, _t->get(),
%attribute_exception(SWIG_AttributeError,"read-only 'attr' attribute");)
#endif #endif
%enddef %enddef
%define %attribute_readonly(Class, AttributeType, AttributeName, GetMethod, GetMethodCall)
%define %_attribute_ref_T(Class, Wrap, type, refname, attr) %ignore Class::GetMethod();
%ignore Class::refname(); %ignore Class::GetMethod() const;
%ignore Class::refname() const; %immutable Class::AttributeName;
%_attribute(%arg(Class), Wrap, %arg(type), %extend Class {
attr, _t->refname(), _t->refname() = _val) AttributeType AttributeName;
%enddef }
#if defined(__cplusplus) && defined(SWIG_ATTRIBUTE_TEMPLATE)
%define %attribute_ref_T(Class, Wrap, type, refname, attr...) %{
#if #attr == "" template < class C > inline AttributeType %mangle(Class) ##_## AttributeName ## _get(const C* self_) {
%_attribute_ref_T(%arg(Class), Wrap, %arg(type), refname, refname) return GetMethodCall;
}
template < class C > inline AttributeType %mangle(Class) ##_## AttributeName ## _get(C* self_) {
return GetMethodCall;
}
%}
#else #else
%_attribute_ref_T(%arg(Class), Wrap, %arg(type), refname, attr) %{
#define %mangle(Class) ##_## AttributeName ## _get(self_) GetMethodCall
%}
#endif #endif
%enddef %enddef
// %define %attribute(Class, AttributeType, AttributeName, GetMethod, SetMethod...)
// User versions #if #SetMethod != ""
// %attribute_custom(Class, AttributeType, AttributeName, GetMethod, SetMethod, self_->GetMethod(), self_->SetMethod(val_))
#else
%define %attribute(Class, type, attr, get, set...) %attribute_readonly(Class, AttributeType, AttributeName, GetMethod, self_->GetMethod())
%attribute_T(%arg(Class), %mangle(Class), %arg(type), attr, get, set) #endif
%enddef %enddef
%define %attribute_ref(Class, type, refname, _Type...) %define %attribute2(Class, AttributeType, AttributeName, GetMethod, SetMethod...)
%attribute_ref_T(%arg(Class), %mangle(Class), %arg(type), refname, _Type) #if #SetMethod != ""
%attribute_custom(Class, AttributeType, AttributeName, GetMethod, SetMethod, &self_->GetMethod(), self_->SetMethod(*val_))
#else
%attribute_readonly(Class, AttributeType, AttributeName, GetMethod, &self_->GetMethod())
#endif
%enddef %enddef
%define %attribute_ref(Class, AttributeType, Accessor, AttributeName...)
#if #AttributeName != ""
%attribute_custom(Class, AttributeType, AttributeName, Accessor, Accessor, self_->Accessor(), self_->Accessor() = val_)
#else
%attribute_custom(Class, AttributeType, Accessor, Accessor, Accessor, self_->Accessor(), self_->Accessor() = val_)
#endif
%enddef
%define %attribute2_ref(Class, AttributeType, Accessor, AttributeName...)
#if #AttributeName != ""
%attribute_custom(Class, AttributeType, AttributeName, Accessor, Accessor, &self_->Accessor(), self_->Accessor() = *val_)
#else
%attribute_custom(Class, AttributeType, Accessor, Accessor, Accessor, &self_->Accessor(), self_->Accessor() = *val_)
#endif
%enddef