diff options
author | Mark Gossage <mark@gossage.cjb.net> | 2008-03-27 01:58:30 +0000 |
---|---|---|
committer | Mark Gossage <mark@gossage.cjb.net> | 2008-03-27 01:58:30 +0000 |
commit | 11647d87e8f3fab24a0b265555ff17847ed04405 (patch) | |
tree | a316f7abe8d269afc4aa560f8dec0c4973d0fabf /Examples/lua | |
parent | 97b910d7261c7019404fa53fefedebe6149726f9 (diff) | |
download | swig-11647d87e8f3fab24a0b265555ff17847ed04405.tar.gz |
[lua] Added a typemap DISOWN for SWIGTYPE* and SWIGTYPE[], and support for %delobject feature.
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@10326 626c5289-ae23-0410-ae9c-e8d60b6d4f22
Diffstat (limited to 'Examples/lua')
-rw-r--r-- | Examples/lua/check.list | 1 | ||||
-rw-r--r-- | Examples/lua/embed2/embed2.c | 2 | ||||
-rw-r--r-- | Examples/lua/exception/runme.lua | 33 | ||||
-rw-r--r-- | Examples/lua/functor/runme.lua | 2 | ||||
-rw-r--r-- | Examples/lua/owner/Makefile | 19 | ||||
-rw-r--r-- | Examples/lua/owner/example.cxx | 67 | ||||
-rw-r--r-- | Examples/lua/owner/example.h | 54 | ||||
-rw-r--r-- | Examples/lua/owner/example.i | 35 | ||||
-rw-r--r-- | Examples/lua/owner/runme.lua | 104 |
9 files changed, 315 insertions, 2 deletions
diff --git a/Examples/lua/check.list b/Examples/lua/check.list index c8e09c493..587318e25 100644 --- a/Examples/lua/check.list +++ b/Examples/lua/check.list @@ -10,6 +10,7 @@ funcptr3 functest functor import +owner pointer simple variables diff --git a/Examples/lua/embed2/embed2.c b/Examples/lua/embed2/embed2.c index 12c81735e..e0010d28e 100644 --- a/Examples/lua/embed2/embed2.c +++ b/Examples/lua/embed2/embed2.c @@ -164,7 +164,7 @@ int main(int argc,char* argv[]) { int ok;
int res;
char str[80];
- printf("[C] Welcome to the simple embedded Lua example\n");
+ printf("[C] Welcome to the simple embedded Lua example v2\n");
printf("[C] We are in C\n");
printf("[C] opening a Lua state & loading the libraries\n");
L=lua_open();
diff --git a/Examples/lua/exception/runme.lua b/Examples/lua/exception/runme.lua index 63299888e..39b2d6da8 100644 --- a/Examples/lua/exception/runme.lua +++ b/Examples/lua/exception/runme.lua @@ -61,3 +61,36 @@ for i=1,3 do end
end
end
+
+-- this is a bit crazy, but it shows obtaining of the stacktrace
+function a()
+ b()
+end
+function b()
+ t:message()
+end
+print [[
+Now lets call function a()
+ which calls b()
+ which calls into C++
+ which will throw an exception!]]
+ok,res=pcall(a)
+if ok then
+ print " that worked! Funny"
+else
+ print(" call failed with error:",res)
+end
+print "Now lets do the same using xpcall(a,debug.traceback)"
+ok,res=xpcall(a,debug.traceback)
+if ok then
+ print " that worked! Funny"
+else
+ print(" call failed with error:",res)
+end
+print "As you can see, the xpcall gives a nice stacktrace to work with"
+
+
+ok,res=pcall(a)
+print(ok,res)
+ok,res=xpcall(a,debug.traceback)
+print(ok,res)
diff --git a/Examples/lua/functor/runme.lua b/Examples/lua/functor/runme.lua index 66741041c..adf124ac6 100644 --- a/Examples/lua/functor/runme.lua +++ b/Examples/lua/functor/runme.lua @@ -19,6 +19,6 @@ for i=0,100 do a(i) -- Note: function call b(math.sqrt(i)) -- Note: function call end -print("int sum 0..100 is",a:result(),"(expected 5050") +print("int sum 0..100 is",a:result(),"(expected 5050)") print("double sum 0..100 is",b:result(),"(expected ~771.46)") diff --git a/Examples/lua/owner/Makefile b/Examples/lua/owner/Makefile new file mode 100644 index 000000000..1fe68ec7f --- /dev/null +++ b/Examples/lua/owner/Makefile @@ -0,0 +1,19 @@ +TOP = ../..
+SWIG = $(TOP)/../preinst-swig
+CXXSRCS = example.cxx
+TARGET = example
+INTERFACE = example.i
+LIBS = -lm
+
+all::
+ $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \
+ TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' lua_cpp
+
+static::
+ $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \
+ TARGET='mylua' INTERFACE='$(INTERFACE)' lua_cpp_static
+
+clean::
+ $(MAKE) -f $(TOP)/Makefile lua_clean
+
+check: all
diff --git a/Examples/lua/owner/example.cxx b/Examples/lua/owner/example.cxx new file mode 100644 index 000000000..33db33941 --- /dev/null +++ b/Examples/lua/owner/example.cxx @@ -0,0 +1,67 @@ +/* File : example.c */
+
+#include "example.h"
+#define M_PI 3.14159265358979323846
+
+/* Move the shape to a new location */
+void Shape::move(double dx, double dy) {
+ x += dx;
+ y += dy;
+}
+
+int Shape::nshapes = 0;
+
+double Circle::area(void) {
+ return M_PI*radius*radius;
+}
+
+double Circle::perimeter(void) {
+ return 2*M_PI*radius;
+}
+
+double Square::area(void) {
+ return width*width;
+}
+
+double Square::perimeter(void) {
+ return 4*width;
+}
+
+Circle* createCircle(double w)
+{
+ return new Circle(w);
+}
+
+Square* createSquare(double w)
+{
+ return new Square(w);
+}
+
+ShapeOwner::ShapeOwner() {printf(" ShapeOwner(%p)\n",this);}
+ShapeOwner::~ShapeOwner()
+{
+ printf(" ~ShapeOwner(%p)\n",this);
+ for(unsigned i=0;i<shapes.size();i++)
+ delete shapes[i];
+}
+
+void ShapeOwner::add(Shape* ptr) // this method takes ownership of the object
+{
+ shapes.push_back(ptr);
+}
+
+Shape* ShapeOwner::get(int idx) // this pointer is still owned by the class (assessor)
+{
+ if (idx<0 || idx>=shapes.size())
+ return NULL;
+ return shapes[idx];
+}
+
+Shape* ShapeOwner::remove(int idx) // this method returns memory which must be deleted
+{
+ if (idx<0 || idx>=shapes.size())
+ return NULL;
+ Shape* ptr=shapes[idx];
+ shapes.erase(shapes.begin()+idx);
+ return ptr;
+}
diff --git a/Examples/lua/owner/example.h b/Examples/lua/owner/example.h new file mode 100644 index 000000000..b00568025 --- /dev/null +++ b/Examples/lua/owner/example.h @@ -0,0 +1,54 @@ +/* File : example.h */
+#include <vector>
+
+class Shape {
+public:
+ Shape() {
+ nshapes++;
+ }
+ virtual ~Shape() {
+ nshapes--;
+ };
+ double x, y;
+ void move(double dx, double dy);
+ virtual double area(void) = 0;
+ virtual double perimeter(void) = 0;
+ static int nshapes;
+};
+
+class Circle : public Shape {
+private:
+ double radius;
+public:
+ Circle(double r) : radius(r) { };
+ virtual double area(void);
+ virtual double perimeter(void);
+};
+
+class Square : public Shape {
+private:
+ double width;
+public:
+ Square(double w) : width(w) { };
+ virtual double area(void);
+ virtual double perimeter(void);
+};
+
+
+Circle* createCircle(double w); // this method creates a new object
+Square* createSquare(double w); // this method creates a new object
+
+class ShapeOwner {
+private:
+ std::vector<Shape*> shapes;
+ ShapeOwner(const ShapeOwner&); // no copying
+ ShapeOwner& operator=(const ShapeOwner&); // no copying
+public:
+ ShapeOwner();
+ ~ShapeOwner();
+ void add(Shape* ptr); // this method takes ownership of the object
+ Shape* get(int idx); // this pointer is still owned by the class (assessor)
+ Shape* remove(int idx); // this method returns memory which must be deleted
+};
+
+
diff --git a/Examples/lua/owner/example.i b/Examples/lua/owner/example.i new file mode 100644 index 000000000..0be5bccc3 --- /dev/null +++ b/Examples/lua/owner/example.i @@ -0,0 +1,35 @@ +/* File : example.i */
+%module example
+
+%{
+#include "example.h"
+%}
+
+// before we grab the header file, we must warn SWIG about some of these functions.
+
+// these functions create data, so must be managed
+%newobject createCircle;
+%newobject createSquare;
+
+// this method returns as pointer which must be managed
+%newobject ShapeOwner::remove;
+
+// you cannot use %delobject on ShapeOwner::add()
+// as this disowns the ShapeOwner, not the Shape (oops)
+//%delobject ShapeOwner::add(Shape*); DO NOT USE
+
+// either you can use a new function (such as this)
+/*%delobject add_Shape;
+%inline %{
+void add_Shape(Shape* s,ShapeOwner* own){own->add(s);}
+%}*/
+
+// or a better solution is a typemap
+%apply SWIGTYPE *DISOWN {Shape* ptr};
+
+
+//%ignore ShapeOwner::add;
+
+// now we can grab the header file
+%include "example.h"
+
diff --git a/Examples/lua/owner/runme.lua b/Examples/lua/owner/runme.lua new file mode 100644 index 000000000..d2d8a9c6f --- /dev/null +++ b/Examples/lua/owner/runme.lua @@ -0,0 +1,104 @@ +-- Operator overloading example
+---- importing ----
+if string.sub(_VERSION,1,7)=='Lua 5.0' then
+ -- lua5.0 doesnt have a nice way to do this
+ lib=loadlib('example.dll','luaopen_example') or loadlib('example.so','luaopen_example')
+ assert(lib)()
+else
+ -- lua 5.1 does
+ require('example')
+end
+
+print "ok, lets test Lua's ownership of C++ objects"
+print("Currently there are",example.Shape_nshapes,"shapes (there should be 0)")
+
+print "\nLets make a couple"
+a=example.Square(10)
+b=example.Circle(1)
+print("Currently there are",example.Shape_nshapes,"shapes (there should be 2)")
+
+print "\nNote lets use the createX functions"
+c=example.createCircle(5)
+d=example.createSquare(3)
+print("Currently there are",example.Shape_nshapes,"shapes (there should be 4)")
+
+print "\nWe will run the garbage collector & see if they are till here"
+collectgarbage()
+print("Currently there are",example.Shape_nshapes,"shapes (there should be 4)")
+
+print "\nLets get rid of them all, collect garbage & see if they are till here"
+a,b,c,d=nil,nil,nil,nil
+collectgarbage()
+print("Currently there are",example.Shape_nshapes,"shapes (there should be 0)")
+
+print "\nLets start putting stuff into the ShapeOwner"
+print "The ShapeOwner now owns the shapes, but Lua still has pointers to them"
+o=example.ShapeOwner()
+a=example.Square(10)
+b=example.Circle(1)
+o:add(a)
+o:add(b)
+o:add(example.createSquare(5))
+print("Currently there are",example.Shape_nshapes,"shapes (there should be 3)")
+
+print "\nWe will nil our references,run the garbage collector & see if they are till here"
+print "they should be, as the ShapeOwner owns them"
+a,b=nil,nil
+collectgarbage()
+print("Currently there are",example.Shape_nshapes,"shapes (there should be 3)")
+
+print "\nWe will access them and check that they are still valid"
+a=o:get(0)
+b=o:get(1)
+print(" Area's are",a:area(),b:area(),o:get(2):area())
+collectgarbage()
+print("Currently there are",example.Shape_nshapes,"shapes (there should be 3)")
+
+print "\nWe will remove one from the C++ owner & pass its ownership to Lua,"
+print " then check that they are still unchanged"
+a,b=nil,nil
+a=o:remove(0) -- a now owns it
+collectgarbage()
+print("Currently there are",example.Shape_nshapes,"shapes (there should be 3)")
+
+print "\nDelete the ShapeOwner (this should destroy two shapes),"
+print " but we have one left in Lua"
+o=nil
+collectgarbage()
+print("Currently there are",example.Shape_nshapes,"shapes (there should be 1)")
+
+print "\nFinal tidy up "
+a=nil
+collectgarbage()
+print("Currently there are",example.Shape_nshapes,"shapes (there should be 0)")
+
+
+print "Final test, we will create some Shapes & pass them around like mad"
+print "If there is any memory leak, you will see it in the memory usage"
+io.flush()
+sh={}
+-- make some objects
+for i=0,10 do
+ a=example.Circle(i)
+ b=example.Square(i)
+ sh[a]=true
+ sh[b]=true
+end
+o=example.ShapeOwner()
+for i=0,10000 do
+ for k,_ in pairs(sh) do
+ o:add(k)
+ end
+ sh={} -- clear it
+ while true do
+ a=o:remove(0)
+ if a==nil then break end
+ sh[a]=true
+ end
+ if i%100==0 then collectgarbage() end
+end
+print "done"
+o,sh=nil,nil
+collectgarbage()
+print("Currently there are",example.Shape_nshapes,"shapes (there should be 0)")
+print "thats all folks!"
\ No newline at end of file |