Add %attributeval and %attributestring to attribute.swg library

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@11128 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
William S Fulton 2009-02-13 22:42:45 +00:00
commit 589eb8e509
6 changed files with 261 additions and 15 deletions

View file

@ -1,6 +1,12 @@
Version 1.3.39 (in progress) Version 1.3.39 (in progress)
============================ ============================
2008-02-14: wsfulton
Extend attribute library support for structs/classes and the accessor functions use
pass/return by value semantics. Two new macros are available and usage is identical
to %attribute. These are %attributeval for structs/classes and %attributestring for
string classes, like std::string. See attribute.swg for more details.
2008-02-13: wsfulton 2008-02-13: wsfulton
Add support for %extend and memberin typemaps. Previously the memberin typemaps were Add support for %extend and memberin typemaps. Previously the memberin typemaps were
ignored for member variables within a %extend block. ignored for member variables within a %extend block.

View file

@ -0,0 +1,78 @@
// Ported from Python li_attribute_runme.py
using System;
using li_attributeNamespace;
public class li_attribute_runme {
public static void Main() {
A aa = new A(1,2,3);
if (aa.a != 1)
throw new ApplicationException("error");
aa.a = 3;
if (aa.a != 3)
throw new ApplicationException("error");
if (aa.b != 2)
throw new ApplicationException("error");
aa.b = 5;
if (aa.b != 5)
throw new ApplicationException("error");
if (aa.d != aa.b)
throw new ApplicationException("error");
if (aa.c != 3)
throw new ApplicationException("error");
//aa.c = 5;
//if (aa.c != 3)
// throw new ApplicationException("error");
Param_i pi = new Param_i(7);
if (pi.value != 7)
throw new ApplicationException("error");
pi.value=3;
if (pi.value != 3)
throw new ApplicationException("error");
B b = new B(aa);
if (b.a.c != 3)
throw new ApplicationException("error");
// class/struct attribute with get/set methods using return/pass by reference
MyFoo myFoo = new MyFoo();
myFoo.x = 8;
MyClass myClass = new MyClass();
myClass.Foo = myFoo;
if (myClass.Foo.x != 8)
throw new ApplicationException("error");
// class/struct attribute with get/set methods using return/pass by value
MyClassVal myClassVal = new MyClassVal();
if (myClassVal.ReadWriteFoo.x != -1)
throw new ApplicationException("error");
if (myClassVal.ReadOnlyFoo.x != -1)
throw new ApplicationException("error");
myClassVal.ReadWriteFoo = myFoo;
if (myClassVal.ReadWriteFoo.x != 8)
throw new ApplicationException("error");
if (myClassVal.ReadOnlyFoo.x != 8)
throw new ApplicationException("error");
// string attribute with get/set methods using return/pass by value
MyStringyClass myStringClass = new MyStringyClass("initial string");
if (myStringClass.ReadWriteString != "initial string")
throw new ApplicationException("error");
if (myStringClass.ReadOnlyString != "initial string")
throw new ApplicationException("error");
myStringClass.ReadWriteString = "changed string";
if (myStringClass.ReadWriteString != "changed string")
throw new ApplicationException("error");
if (myStringClass.ReadOnlyString != "changed string")
throw new ApplicationException("error");
}
}

View file

@ -93,9 +93,11 @@ struct MyFoo; // %attribute2 does not work with templates
%template(Param_i) Param<int>; %template(Param_i) Param<int>;
// class/struct attribute with get/set methods using return/pass by reference
%attribute2(MyClass, MyFoo, Foo, GetFoo, SetFoo); %attribute2(MyClass, MyFoo, Foo, GetFoo, SetFoo);
%inline %{ %inline %{
struct MyFoo { struct MyFoo {
MyFoo() : x(-1) {}
int x; int x;
}; };
class MyClass { class MyClass {
@ -106,3 +108,32 @@ struct MyFoo; // %attribute2 does not work with templates
}; };
%} %}
// class/struct attribute with get/set methods using return/pass by value
%attributeval(MyClassVal, MyFoo, ReadWriteFoo, GetFoo, SetFoo);
%attributeval(MyClassVal, MyFoo, ReadOnlyFoo, GetFoo);
%inline %{
class MyClassVal {
MyFoo foo;
public:
MyFoo GetFoo() { return foo; }
void SetFoo(MyFoo other) { foo = other; }
};
%}
// string attribute with get/set methods using return/pass by value
%include <std_string.i>
%attributestring(MyStringyClass, std::string, ReadWriteString, GetString, SetString);
%attributestring(MyStringyClass, std::string, ReadOnlyString, GetString);
%inline %{
class MyStringyClass {
std::string str;
public:
MyStringyClass(const std::string &val) : str(val) {}
std::string GetString() { return str; }
void SetString(std::string other) { str = other; }
};
%}

View file

@ -10,7 +10,6 @@ if (aa.a != 3)
error("aa.a = %i",aa.a) error("aa.a = %i",aa.a)
endif endif
if (aa.b != 2) if (aa.b != 2)
error(aa.b) error(aa.b)
endif endif
@ -19,8 +18,6 @@ if (aa.b != 5)
error error
endif endif
if (aa.d != aa.b) if (aa.d != aa.b)
error error
endif endif
@ -39,14 +36,13 @@ if (pi.value != 3)
error error
endif endif
b = li_attribute.B(aa); b = li_attribute.B(aa);
if (b.a.c != 3) if (b.a.c != 3)
error error
endif endif
# class/struct attribute with get/set methods using return/pass by reference
myFoo = li_attribute.MyFoo(); myFoo = li_attribute.MyFoo();
myFoo.x = 8; myFoo.x = 8;
myClass = li_attribute.MyClass(); myClass = li_attribute.MyClass();
@ -55,3 +51,35 @@ if (myClass.Foo.x != 8)
error error
endif endif
# class/struct attribute with get/set methods using return/pass by value
myClassVal = li_attribute.MyClassVal();
if (myClassVal.ReadWriteFoo.x != -1)
error
endif
if (myClassVal.ReadOnlyFoo.x != -1)
error
endif
myClassVal.ReadWriteFoo = myFoo;
if (myClassVal.ReadWriteFoo.x != 8)
error
endif
if (myClassVal.ReadOnlyFoo.x != 8)
error
endif
# string attribute with get/set methods using return/pass by value
myStringyClass = li_attribute.MyStringyClass("initial string");
if (myStringyClass.ReadWriteString != "initial string")
error
endif
if (myStringyClass.ReadOnlyString != "initial string")
error
endif
myStringyClass.ReadWriteString = "changed string";
if (myStringyClass.ReadWriteString != "changed string")
error
endif
if (myStringyClass.ReadOnlyString != "changed string")
error
endif

View file

@ -1,3 +1,5 @@
# Ported to C# li_attribute_runme.cs
import li_attribute import li_attribute
aa = li_attribute.A(1,2,3) aa = li_attribute.A(1,2,3)
@ -9,7 +11,6 @@ if aa.a != 3:
print aa.a print aa.a
raise RuntimeError raise RuntimeError
if aa.b != 2: if aa.b != 2:
print aa.b print aa.b
raise RuntimeError raise RuntimeError
@ -17,8 +18,6 @@ aa.b = 5
if aa.b != 5: if aa.b != 5:
raise RuntimeError raise RuntimeError
if aa.d != aa.b: if aa.d != aa.b:
raise RuntimeError raise RuntimeError
@ -36,17 +35,40 @@ pi.value=3
if pi.value != 3: if pi.value != 3:
raise RuntimeError raise RuntimeError
b = li_attribute.B(aa) b = li_attribute.B(aa)
if b.a.c != 3: if b.a.c != 3:
raise RuntimeError raise RuntimeError
# class/struct attribute with get/set methods using return/pass by reference
myFoo = li_attribute.MyFoo myFoo = li_attribute.MyFoo()
myFoo.x = 8 myFoo.x = 8
myClass = li_attribute.MyClass myClass = li_attribute.MyClass()
myClass.Foo = myFoo myClass.Foo = myFoo
if myClass.Foo.x != 8: if myClass.Foo.x != 8:
raise RuntimeError raise RuntimeError
# class/struct attribute with get/set methods using return/pass by value
myClassVal = li_attribute.MyClassVal()
if myClassVal.ReadWriteFoo.x != -1:
raise RuntimeError
if myClassVal.ReadOnlyFoo.x != -1:
raise RuntimeError
myClassVal.ReadWriteFoo = myFoo
if myClassVal.ReadWriteFoo.x != 8:
raise RuntimeError
if myClassVal.ReadOnlyFoo.x != 8:
raise RuntimeError
# string attribute with get/set methods using return/pass by value
myStringyClass = li_attribute.MyStringyClass("initial string")
if myStringyClass.ReadWriteString != "initial string":
raise RuntimeError
if myStringyClass.ReadOnlyString != "initial string":
raise RuntimeError
myStringyClass.ReadWriteString = "changed string"
if myStringyClass.ReadWriteString != "changed string":
raise RuntimeError
if myStringyClass.ReadOnlyString != "changed string":
raise RuntimeError

View file

@ -11,7 +11,7 @@
The following macros convert a pair of set/get methods The following macros convert a pair of set/get methods
into a "native" attribute. into a "native" attribute.
Use %attribute when you have a pair of get/set methods Use %attribute when you have a pair of get/set methods to a primitive type
like in: like in:
%attribute(A, int, a, get_a, set_a); %attribute(A, int, a, get_a, set_a);
@ -27,8 +27,8 @@
%attribute(A, int, c, get_c); %attribute(A, int, c, get_c);
Use %attributeref when you have const/non-const reference Use %attributeref when you have const/non-const reference access methods
access methods, like in: for primitive types or class/structs, like in:
%attributeref(A, int, b); %attributeref(A, int, b);
@ -99,6 +99,40 @@
where %arg() 'normalizes' 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 by the comma. argument, otherwise the macro will get confused by the comma.
The %attributeval is the same as %attribute, but should be used when the type
is a class/struct (ie a non-primitive type) and when the get and set methods
return/pass by value. The following is very similar to the above example, but
note that the access is by value rather than reference.
%attributeval(MyClassVal, MyFoo, ReadWriteFoo, GetFoo, SetFoo);
%attributeval(MyClassVal, MyFoo, ReadOnlyFoo, GetFoo);
%inline %{
class MyClassVal {
MyFoo foo;
public:
MyFoo GetFoo() { return foo; }
void SetFoo(MyFoo other) { foo = other; }
};
%}
The %attributestring is the same as %attributeval, but should be used for string
class types, which are unusual as they are a class on the C++ side, but normally an
immutable/primitive type in the target language. Example usage for std::string:
%include <std_string.i>
%attributestring(MyStringyClass, std::string, ReadWriteString, GetString, SetString);
%attributestring(MyStringyClass, std::string, ReadOnlyString, GetString);
%inline %{
class MyStringyClass {
std::string str;
public:
MyStringyClass(const std::string &val) : str(val) {}
std::string GetString() { return str; }
void SetString(std::string other) { str = other; }
};
%}
*/ */
// //
@ -203,3 +237,50 @@
#endif #endif
%enddef %enddef
%define %attributeval(Class, AttributeType, AttributeName, GetMethod, SetMethod...)
%{
#define %mangle(Class) ##_## AttributeName ## _get(self_) new AttributeType(self_->GetMethod())
%}
#if #SetMethod != ""
%{
#define %mangle(Class) ##_## AttributeName ## _set(self_, val_) self_->SetMethod(*val_)
%}
#if #SetMethod != #AttributeName
%ignore Class::SetMethod;
#endif
#else
%immutable Class::AttributeName;
#endif
%ignore Class::GetMethod();
%ignore Class::GetMethod() const;
%newobject Class::AttributeName;
%extend Class {
AttributeType AttributeName;
}
%enddef
%define %attributestring(Class, AttributeType, AttributeName, GetMethod, SetMethod...)
%{
#define %mangle(Class) ##_## AttributeName ## _get(self_) *new AttributeType(self_->GetMethod())
%}
#if #SetMethod != ""
%{
#define %mangle(Class) ##_## AttributeName ## _set(self_, val_) self_->SetMethod(val_)
%}
#if #SetMethod != #AttributeName
%ignore Class::SetMethod;
#endif
#else
%immutable Class::AttributeName;
#endif
%ignore Class::GetMethod();
%ignore Class::GetMethod() const;
%newobject Class::AttributeName;
%typemap(newfree) const AttributeType &AttributeName "delete $1;// my newfree override"
%extend Class {
AttributeType AttributeName;
}
%enddef