[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
This commit is contained in:
parent
97b910d726
commit
11647d87e8
14 changed files with 377 additions and 19 deletions
|
|
@ -10,6 +10,7 @@ funcptr3
|
|||
functest
|
||||
functor
|
||||
import
|
||||
owner
|
||||
pointer
|
||||
simple
|
||||
variables
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)")
|
||||
|
||||
|
|
|
|||
19
Examples/lua/owner/Makefile
Normal file
19
Examples/lua/owner/Makefile
Normal file
|
|
@ -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
|
||||
67
Examples/lua/owner/example.cxx
Normal file
67
Examples/lua/owner/example.cxx
Normal file
|
|
@ -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;
|
||||
}
|
||||
54
Examples/lua/owner/example.h
Normal file
54
Examples/lua/owner/example.h
Normal file
|
|
@ -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
|
||||
};
|
||||
|
||||
|
||||
35
Examples/lua/owner/example.i
Normal file
35
Examples/lua/owner/example.i
Normal file
|
|
@ -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"
|
||||
|
||||
104
Examples/lua/owner/runme.lua
Normal file
104
Examples/lua/owner/runme.lua
Normal file
|
|
@ -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!"
|
||||
Loading…
Add table
Add a link
Reference in a new issue