Reimplementation of tracking objects in Ruby. Instead of passing the $track flag to
the methods SWIG_Ruby_ConvertPtrAndOwn and SWIG_Ruby_NewPointerObj, now tracking information is held on swig_class. This change reduces significantly reduces the amount of code needed in ruby.cxx, is more robust, and is more cohesive. git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@8082 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
parent
c81c25f671
commit
6c8dd53ee8
4 changed files with 50 additions and 160 deletions
|
|
@ -13,7 +13,7 @@
|
||||||
|
|
||||||
%typemap(argout) Foo** foo {
|
%typemap(argout) Foo** foo {
|
||||||
/* %typemap(argout) Foo** foo */
|
/* %typemap(argout) Foo** foo */
|
||||||
$result = SWIG_NewPointerObj((void *) *$1, $*1_descriptor, $track);
|
$result = SWIG_NewPointerObj((void *) *$1, $*1_descriptor, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
%apply SWIGTYPE *DISOWN {Foo* ownedFoo};
|
%apply SWIGTYPE *DISOWN {Foo* ownedFoo};
|
||||||
|
|
|
||||||
|
|
@ -64,14 +64,12 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Flags for new pointer objects */
|
|
||||||
#define SWIG_TRACK_OBJECTS 0x4
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
VALUE klass;
|
VALUE klass;
|
||||||
VALUE mImpl;
|
VALUE mImpl;
|
||||||
void (*mark)(void *);
|
void (*mark)(void *);
|
||||||
void (*destroy)(void *);
|
void (*destroy)(void *);
|
||||||
|
int trackObjects;
|
||||||
} swig_class;
|
} swig_class;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -108,7 +106,6 @@ SWIGRUNTIME VALUE
|
||||||
SWIG_Ruby_NewPointerObj(void *ptr, swig_type_info *type, int flags)
|
SWIG_Ruby_NewPointerObj(void *ptr, swig_type_info *type, int flags)
|
||||||
{
|
{
|
||||||
int own = flags & SWIG_POINTER_OWN;
|
int own = flags & SWIG_POINTER_OWN;
|
||||||
int track = flags & SWIG_TRACK_OBJECTS;
|
|
||||||
|
|
||||||
char *klass_name;
|
char *klass_name;
|
||||||
swig_class *sklass;
|
swig_class *sklass;
|
||||||
|
|
@ -118,17 +115,24 @@ SWIG_Ruby_NewPointerObj(void *ptr, swig_type_info *type, int flags)
|
||||||
if (!ptr)
|
if (!ptr)
|
||||||
return Qnil;
|
return Qnil;
|
||||||
|
|
||||||
/* Have we already wrapped this pointer? */
|
if (type->clientdata) {
|
||||||
if (track) {
|
sklass = (swig_class *) type->clientdata;
|
||||||
|
|
||||||
|
/* Are we tracking this class and have we already returned this Ruby object? */
|
||||||
|
if (sklass->trackObjects) {
|
||||||
obj = SWIG_RubyInstanceFor(ptr);
|
obj = SWIG_RubyInstanceFor(ptr);
|
||||||
if (obj != Qnil) {
|
if (obj != Qnil) {
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type->clientdata) {
|
/* Create a new Ruby object */
|
||||||
sklass = (swig_class *) type->clientdata;
|
|
||||||
obj = Data_Wrap_Struct(sklass->klass, VOIDFUNC(sklass->mark), (own ? VOIDFUNC(sklass->destroy) : 0), ptr);
|
obj = Data_Wrap_Struct(sklass->klass, VOIDFUNC(sklass->mark), (own ? VOIDFUNC(sklass->destroy) : 0), ptr);
|
||||||
|
|
||||||
|
/* If tracking is on for this class then track this object. */
|
||||||
|
if (sklass->trackObjects) {
|
||||||
|
SWIG_RubyAddTracking(ptr, obj);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
klass_name = (char *) malloc(4 + strlen(type->name) + 1);
|
klass_name = (char *) malloc(4 + strlen(type->name) + 1);
|
||||||
sprintf(klass_name, "TYPE%s", type->name);
|
sprintf(klass_name, "TYPE%s", type->name);
|
||||||
|
|
@ -138,11 +142,6 @@ SWIG_Ruby_NewPointerObj(void *ptr, swig_type_info *type, int flags)
|
||||||
}
|
}
|
||||||
rb_iv_set(obj, "__swigtype__", rb_str_new2(type->name));
|
rb_iv_set(obj, "__swigtype__", rb_str_new2(type->name));
|
||||||
|
|
||||||
/* Keep track of this object if necessary */
|
|
||||||
if (track) {
|
|
||||||
SWIG_RubyAddTracking(ptr, obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -198,16 +197,22 @@ SWIG_Ruby_ConvertPtrAndOwn(VALUE obj, void **ptr, swig_type_info *ty, int flags,
|
||||||
Data_Get_Struct(obj, void, vptr);
|
Data_Get_Struct(obj, void, vptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (own) *own = RDATA(obj)->dfree;
|
||||||
|
|
||||||
/* Check to see if the input object is giving up ownership
|
/* Check to see if the input object is giving up ownership
|
||||||
of the underlying C struct or C++ object. If so then we
|
of the underlying C struct or C++ object. If so then we
|
||||||
need to reset the destructor since the Ruby object no
|
need to reset the destructor since the Ruby object no
|
||||||
longer owns the underlying C++ object.*/
|
longer owns the underlying C++ object.*/
|
||||||
if (own) *own = RDATA(obj)->dfree;
|
|
||||||
|
|
||||||
if (flags & SWIG_POINTER_DISOWN) {
|
if (flags & SWIG_POINTER_DISOWN) {
|
||||||
if (flags & SWIG_TRACK_OBJECTS) {
|
/* Is tracking on for this class? */
|
||||||
/* We are tracking objects. Thus we change the destructor
|
int track = 0;
|
||||||
|
if (ty && ty->clientdata) {
|
||||||
|
swig_class *sklass = (swig_class *) ty->clientdata;
|
||||||
|
track = sklass->trackObjects;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (track) {
|
||||||
|
/* We are tracking objects for this class. Thus we change the destructor
|
||||||
* to SWIG_RubyRemoveTracking. This allows us to
|
* to SWIG_RubyRemoveTracking. This allows us to
|
||||||
* remove the mapping from the C++ to Ruby object
|
* remove the mapping from the C++ to Ruby object
|
||||||
* when the Ruby object is garbage collected. If we don't
|
* when the Ruby object is garbage collected. If we don't
|
||||||
|
|
|
||||||
|
|
@ -39,11 +39,6 @@
|
||||||
#define SWIG_Object VALUE
|
#define SWIG_Object VALUE
|
||||||
#define VOID_Object Qnil
|
#define VOID_Object Qnil
|
||||||
|
|
||||||
/* Ruby $track flag */
|
|
||||||
#define %convertptr_flags $track
|
|
||||||
#define %newpointer_flags $track
|
|
||||||
#define %newinstance_flags $track
|
|
||||||
|
|
||||||
/* Simple overload of the output/constant/exception handling */
|
/* Simple overload of the output/constant/exception handling */
|
||||||
#define SWIG_AppendOutput(result,obj) SWIG_Ruby_AppendOutput(result, obj)
|
#define SWIG_AppendOutput(result,obj) SWIG_Ruby_AppendOutput(result, obj)
|
||||||
#define SWIG_SetConstant(name, obj) rb_define_const($module, name, obj)
|
#define SWIG_SetConstant(name, obj) rb_define_const($module, name, obj)
|
||||||
|
|
|
||||||
|
|
@ -754,13 +754,6 @@ public:
|
||||||
Replaceall(tm,"$disown","0");
|
Replaceall(tm,"$disown","0");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (trackType(pt)) {
|
|
||||||
Replaceall(tm, "$track","SWIG_TRACK_OBJECTS");
|
|
||||||
} else {
|
|
||||||
Replaceall(tm, "$track","0");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Setattr(p,"emit:input",Copy(source));
|
Setattr(p,"emit:input",Copy(source));
|
||||||
Printf(f->code,"%s\n", tm);
|
Printf(f->code,"%s\n", tm);
|
||||||
p = Getattr(p,"tmap:in:next");
|
p = Getattr(p,"tmap:in:next");
|
||||||
|
|
@ -936,15 +929,6 @@ public:
|
||||||
Replaceall(tm,"$arg",Getattr(p,"emit:input"));
|
Replaceall(tm,"$arg",Getattr(p,"emit:input"));
|
||||||
Replaceall(tm,"$input",Getattr(p,"emit:input"));
|
Replaceall(tm,"$input",Getattr(p,"emit:input"));
|
||||||
|
|
||||||
/* Are we tracking the type that is being returned
|
|
||||||
* by this output parameter? */
|
|
||||||
SwigType *pt = Getattr(p,"type");
|
|
||||||
if (trackType(pt)) {
|
|
||||||
Replaceall(tm, "$track","SWIG_TRACK_OBJECTS");
|
|
||||||
} else {
|
|
||||||
Replaceall(tm, "$track","0");
|
|
||||||
}
|
|
||||||
|
|
||||||
Printv(outarg,tm,"\n",NIL);
|
Printv(outarg,tm,"\n",NIL);
|
||||||
need_result = 1;
|
need_result = 1;
|
||||||
p = Getattr(p,"tmap:argout:next");
|
p = Getattr(p,"tmap:argout:next");
|
||||||
|
|
@ -981,94 +965,6 @@ public:
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------
|
|
||||||
* trackType()
|
|
||||||
*
|
|
||||||
* Returns whether this type should be tracked.
|
|
||||||
* --------------------------------------------------------------------- */
|
|
||||||
bool trackType(SwigType* aType) {
|
|
||||||
/* Get the base type */
|
|
||||||
SwigType* baseType = SwigType_base(aType);
|
|
||||||
Node* classNode = classLookup(baseType);
|
|
||||||
|
|
||||||
if (classNode && GetFlag(classNode, "feature:trackobjects")) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* ---------------------------------------------------------------------
|
|
||||||
* setTrackObjectsFlagForConvertPtr()
|
|
||||||
*
|
|
||||||
* Adds "|SWIG_TRACK_OBJECTS" flag to be passed to SWIG_ConvertPtr
|
|
||||||
* --------------------------------------------------------------------- */
|
|
||||||
void setTrackObjectsFlagForConvertPtr(String* originalString) {
|
|
||||||
/* If feature:trackobjects is defined for a class and an object
|
|
||||||
* of that class is giving up ownership of the underlying C++
|
|
||||||
* object, then we need to set the SWIG_TRACK_OBJECTS flag.
|
|
||||||
* This notifies the SWIG_ConvertPtr method so that it can
|
|
||||||
* appropriately reset the free function of the object.*/
|
|
||||||
|
|
||||||
Replaceall(originalString, "SWIG_POINTER_DISOWN",
|
|
||||||
"SWIG_POINTER_DISOWN | SWIG_TRACK_OBJECTS");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------
|
|
||||||
* setTrackObjectsFlagForNewPointer()
|
|
||||||
*
|
|
||||||
* Adds "|SWIG_TRACK_OBJECTS" flag to be passed to SWIG_NewPointer
|
|
||||||
* --------------------------------------------------------------------- */
|
|
||||||
void setTrackObjectsFlagForNewPointer(String* originalString) {
|
|
||||||
/* If feature:trackobjects is defined for a class then
|
|
||||||
* we want to send a flag to the SWIG_NewPointerObj method.
|
|
||||||
* Unfortunately, this implementation is quite awful.
|
|
||||||
* We want to change code like this:
|
|
||||||
*
|
|
||||||
* SWIG_NewPointerObj((void *) result, SWIGTYPE_p_Foo,0);
|
|
||||||
*
|
|
||||||
* To this:
|
|
||||||
*
|
|
||||||
* SWIG_NewPointerObj((void *) result, SWIGTYPE_p_Foo,0|SWIG_TRACK_OBJECTS);
|
|
||||||
*
|
|
||||||
* A better implemenation would be to introduce a $track_objects
|
|
||||||
* marker, similar to how $disown and $owner now work. However,
|
|
||||||
* that would require changing all typemaps that currently
|
|
||||||
* call SWIG_NewPointerObj which did not seem like a good idea.
|
|
||||||
*
|
|
||||||
* The reason why passing a flag to SWIG_NewPointerObj is the best
|
|
||||||
* implemenation is that:
|
|
||||||
* - it already is aware of object tracking since it uses
|
|
||||||
* the SWIG_RubyInstanceFor method - thus this is more
|
|
||||||
* cohesive
|
|
||||||
* - it centers most object tracking code in SWIG_NewPointerObj and
|
|
||||||
* SWIG_ConvertPtr as opposed to scattering it all over the place.
|
|
||||||
* - it allows SWIG_NewPointerObj to be optimized so that
|
|
||||||
* SWIG_RubyInstanceFor is called only for objects that the
|
|
||||||
* user as marked to track */
|
|
||||||
|
|
||||||
/* Look for the string SWIG_NewPointerObj */
|
|
||||||
char* start = Strstr(originalString, "SWIG_NewPointerObj");
|
|
||||||
|
|
||||||
if (start) {
|
|
||||||
/* Okay - found it. We now replace ); with "|SWIG_TRACK_OBJECTS);"
|
|
||||||
* Of course, we only want to replace the first occurence we see.
|
|
||||||
* Note this code is easily subverted if a user types in
|
|
||||||
* "SWIG_NewPointerObj(a,b) ;
|
|
||||||
*
|
|
||||||
* It would be best if we could call the replace method
|
|
||||||
* on start, but that does not work because replace only
|
|
||||||
* works on string objects (although the documenation
|
|
||||||
* implies otherwise.*/
|
|
||||||
String* replaceString = NewString(start);
|
|
||||||
Replace(replaceString, ");", "|SWIG_TRACK_OBJECTS);", DOH_REPLACE_FIRST);
|
|
||||||
Replace(originalString, start, replaceString, DOH_REPLACE_FIRST);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------
|
/* ---------------------------------------------------------------------
|
||||||
* functionWrapper()
|
* functionWrapper()
|
||||||
*
|
*
|
||||||
|
|
@ -1281,12 +1177,6 @@ public:
|
||||||
else
|
else
|
||||||
Replaceall(tm,"$owner", "0");
|
Replaceall(tm,"$owner", "0");
|
||||||
|
|
||||||
if (trackType(t)) {
|
|
||||||
Replaceall(tm, "$track","SWIG_TRACK_OBJECTS");
|
|
||||||
} else {
|
|
||||||
Replaceall(tm, "$track","0");
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
// FIXME: this will not try to unwrap directors returned as non-director
|
// FIXME: this will not try to unwrap directors returned as non-director
|
||||||
// base class pointers!
|
// base class pointers!
|
||||||
|
|
@ -1523,12 +1413,6 @@ public:
|
||||||
Replaceall(tm,"$result","_val");
|
Replaceall(tm,"$result","_val");
|
||||||
Replaceall(tm,"$target","_val");
|
Replaceall(tm,"$target","_val");
|
||||||
Replaceall(tm,"$source",name);
|
Replaceall(tm,"$source",name);
|
||||||
if (trackType(t)) {
|
|
||||||
Replaceall(tm, "$track","SWIG_TRACK_OBJECTS");
|
|
||||||
} else {
|
|
||||||
Replaceall(tm, "$track","0");
|
|
||||||
}
|
|
||||||
|
|
||||||
Printv(getf->code,tm, NIL);
|
Printv(getf->code,tm, NIL);
|
||||||
} else {
|
} else {
|
||||||
Swig_warning(WARN_TYPEMAP_VAROUT_UNDEF, input_file, line_number,
|
Swig_warning(WARN_TYPEMAP_VAROUT_UNDEF, input_file, line_number,
|
||||||
|
|
@ -1550,11 +1434,6 @@ public:
|
||||||
Replaceall(tm,"$input","_val");
|
Replaceall(tm,"$input","_val");
|
||||||
Replaceall(tm,"$source","_val");
|
Replaceall(tm,"$source","_val");
|
||||||
Replaceall(tm,"$target",name);
|
Replaceall(tm,"$target",name);
|
||||||
if (trackType(t)) {
|
|
||||||
Replaceall(tm, "$track","SWIG_TRACK_OBJECTS");
|
|
||||||
} else {
|
|
||||||
Replaceall(tm, "$track","0");
|
|
||||||
}
|
|
||||||
Printv(setf->code,tm,"\n",NIL);
|
Printv(setf->code,tm,"\n",NIL);
|
||||||
} else {
|
} else {
|
||||||
Swig_warning(WARN_TYPEMAP_VARIN_UNDEF, input_file, line_number,
|
Swig_warning(WARN_TYPEMAP_VARIN_UNDEF, input_file, line_number,
|
||||||
|
|
@ -1840,6 +1719,18 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check to see if tracking is enabled for this class.
|
||||||
|
*/
|
||||||
|
void handleTrackDirective(Node *n) {
|
||||||
|
int trackObjects = GetFlag(n, "feature:trackobjects");
|
||||||
|
if (trackObjects) {
|
||||||
|
Printf(klass->init, "c%s.trackObjects = 1;\n", klass->name);
|
||||||
|
} else {
|
||||||
|
Printf(klass->init, "c%s.trackObjects = 0;\n", klass->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------
|
/* ----------------------------------------------------------------------
|
||||||
* classHandler()
|
* classHandler()
|
||||||
* ---------------------------------------------------------------------- */
|
* ---------------------------------------------------------------------- */
|
||||||
|
|
@ -1898,6 +1789,7 @@ public:
|
||||||
handleBaseClasses(n);
|
handleBaseClasses(n);
|
||||||
handleMarkFuncDirective(n);
|
handleMarkFuncDirective(n);
|
||||||
handleFreeFuncDirective(n);
|
handleFreeFuncDirective(n);
|
||||||
|
handleTrackDirective(n);
|
||||||
|
|
||||||
if (multipleInheritance) {
|
if (multipleInheritance) {
|
||||||
Printv(klass->init, "rb_include_module(", klass->vname, ", ", klass->mImpl, ");\n", NIL);
|
Printv(klass->init, "rb_include_module(", klass->vname, ", ", klass->mImpl, ");\n", NIL);
|
||||||
|
|
@ -2463,7 +2355,6 @@ public:
|
||||||
sprintf(source, "obj%d", idx++);
|
sprintf(source, "obj%d", idx++);
|
||||||
Replaceall(tm, "$input", source);
|
Replaceall(tm, "$input", source);
|
||||||
Replaceall(tm, "$owner", "0");
|
Replaceall(tm, "$owner", "0");
|
||||||
Replaceall(tm, "$track", "0");
|
|
||||||
Printv(wrap_args, tm, "\n", NIL);
|
Printv(wrap_args, tm, "\n", NIL);
|
||||||
Wrapper_add_localv(w, source, "VALUE", source, "= Qnil", NIL);
|
Wrapper_add_localv(w, source, "VALUE", source, "= Qnil", NIL);
|
||||||
Printv(arglist, source, NIL);
|
Printv(arglist, source, NIL);
|
||||||
|
|
@ -2616,7 +2507,6 @@ public:
|
||||||
} else {
|
} else {
|
||||||
Replaceall(tm,"$disown","0");
|
Replaceall(tm,"$disown","0");
|
||||||
}
|
}
|
||||||
Replaceall(tm,"$track","0");
|
|
||||||
Replaceall(tm, "$result", "c_result");
|
Replaceall(tm, "$result", "c_result");
|
||||||
Printv(w->code, tm, "\n", NIL);
|
Printv(w->code, tm, "\n", NIL);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -2704,9 +2594,9 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
String *runtimeCode() {
|
String *runtimeCode() {
|
||||||
String *s = Swig_include_sys("rubydef.swg");
|
String *s = Swig_include_sys("rubyrun.swg");
|
||||||
if (!s) {
|
if (!s) {
|
||||||
Printf(stderr, "*** Unable to open 'rubydef.swg'\n");
|
Printf(stderr, "*** Unable to open 'rubyruntime.swg'\n");
|
||||||
s = NewString("");
|
s = NewString("");
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue