From: William S F. <ws...@fu...> - 2006-11-21 22:45:08
|
Tamas Szekeres wrote: > William, > > After making some further tests depending on the function type (static > / non static) and the %newobject feature specification the > swigCMemOwner member should be set as: > > %newobject static swigCMemOwner > > yes no null > no no this > yes yes null > no yes new object() > This last one will never work as the 'new object()' is instantly reachable and can therefore be collected. > To achieve this functionality I have used the following typemaps > > %define %owner(OWNER, TYPE) > %typemap(csout, excode=SWIGEXCODE, new="1") TYPE & { > $csclassname ret = new $csclassname($imcall, $owner? null : > OWNER);$excode > return ret; > } > %typemap(csout, excode=SWIGEXCODE, new="1") TYPE *, TYPE [], TYPE > (CLASS::*) { > IntPtr cPtr = $imcall; > $csclassname ret = (cPtr == IntPtr.Zero) ? null : new > $csclassname(cPtr, $owner? null : OWNER);$excode > return ret; > } > %enddef > > #define %object_owner %owner(this, SWIGTYPE) > #define %static_owner %owner(new object(), SWIGTYPE) > > One should use the %object_owner and %static_owner to manually switch > between the proper typemap sets. > However it would be much easier if I could write separate typemaps for > the static and non static members. Is it possible? > There is something fundamental to take on board about typemaps. They apply to C/C++ types. They are applied independent of whether you are wrapping a static method, global function, member method, template function etc. So the answer is no. You are trying to solve a problem which requires apriori information about the code. SWIG can never deduce this information from the interface and so it requires user intervention. SWIG is a only a semi-automated wrapping tool, largely because of the ambiguities that C/C++ have in the interface prevent it from making it fully automated. It would be possible to provide some general framework for all this, but then you have to impose restrictions on the user. For example, the module class could contain a static member variable for references, say private static Object staticReference; which you could then use: #define %static_owner %owner(staticReference, SWIGTYPE) But this means the solution is not thread safe. You could then make staticReference thread local. Then you are imposing a performance penalty on single thread users. The solution also needs to cover arrays. There is no perfect general solution. As it stands, SWIG is customisable enough to solve all of the problems on a case by case basis. It is up to the user to decide what is best and implement it. What would be really useful is to add some more memory management examples to the documentation covering the scenario you talk about. Personally, I'd make it simpler by keeping swigCMemOwn as a flag and add in a 3rd member variable for mirroring the underlying C++ reference, as I previously mentioned. William > Best Regards, > > Tamas > > > > 2006/11/11, Tamas Szekeres <sze...@gm...>: >> William, >> >> > >> > You have identified a premature garbage collection issue with the >> > parentObj/childObj which is a known problem. I think you are solving >> > what is described in >> Java.html#java_memory_management_member_variables ? >> > I don't see how your replacement of the bool swigCMemOwn is going to >> > work with objects returned by value/pointer/reference. Currently the >> > flag is needed to determine if the class should delete the memory. What >> > does swigCMemOwner get set to when a method returns an object by >> > reference/pointer? >> > >> >> swigCMemOwner would be a more general notation of the object ownership >> since not only the fact of the ownership is notated but the owner >> itself. However I would set swigCMemOwner = null if the owner is the >> same object. >> In my approach theoretically the following replacements are made: >> >> swigCMemOwn = false => swigCMemOwner = null >> swigCMemOwn = true => swigCMemOwner = [the owner object >> reference] >> >> But indeed - as you have mentioned - to support this issue the most >> problematic typemaps are >> >> %typemap(csout, excode=SWIGEXCODE, new="1") SWIGTYPE & { >> $csclassname ret = new $csclassname($imcall, $owner);$excode >> return ret; >> } >> %typemap(csout, excode=SWIGEXCODE, new="1") SWIGTYPE *, SWIGTYPE [], >> SWIGTYPE (CLASS::*) { >> IntPtr cPtr = $imcall; >> $csclassname ret = (cPtr == IntPtr.Zero) ? null : new >> $csclassname(cPtr, $owner);$excode >> return ret; >> } >> >> In the current implementation $owner is replaced with "true" on >> %newobject otherwise replaced with "false". >> >> However for my approach to work this behaviour should be changed as >> $owner is replaced with "this" on %newobject otherwise replaced with >> "null". >> >> Would it be so difficult to support this? >> >> BTW: Do we have an option to write csout typemaps selectively for >> %newobjects? >> >> >> > I don't follow all of your DISOWN typemap. This is a different problem, >> > but it is probably the same solution outlined in >> > Java.html#java_memory_management_objects ? >> > >> >> Because we are dealing with how to maintain the object ownership >> properly we should also >> support how to control it declaratively because the user would want >> modify the default behaviour is some cases. >> >> > In the next iteration of SWIG I was thinking of adding in a 3rd member >> > variable in both Java and C# for holding references. SWIG needs this >> > reference by default for when an object is a member variable. Consider: >> > >> > struct B {}; >> > >> > struct A { >> > B* b; >> > ~A(); >> > }; >> > >> > C#: >> > >> > A a = new A(); >> > B b = a.b; >> > // a could be collected at this point. >> > Use b ... => disaster, but only if A destructor destroys memory of b >> > >> > The extra reference mentioned in the links above would solve this >> > problem, but this should be generated by default for public member >> > access. However, the issue you are talking about where you call a >> member >> > method that returns a reference or pointer to a member variable >> requires >> > a user to decide whether or not the extra reference is required, as the >> > reference/pointer could be to static data, in which case the parent >> > object can be safely collected. As a rule, I do use this extra >> reference >> > approach whenever an object is returned by reference in our code, as >> all >> > our reference returns are references to member variables as a strict >> rule. >> > >> >> Hmmm... I think it would be much more complicated to follow. >> >> >> Best Regards, >> >> Tamas Szekeres >> > |