From: Matt S. <mes...@gm...> - 2009-03-11 06:40:43
|
Why does the wrapper for std::vector<T> implement the non-generic IEnumerable? It seems like it's fairly easy to modify the wrapper to implement the generic IEnumerable. -Matt Sprague |
From: David P. <dpi...@me...> - 2009-03-11 15:12:37
|
Yeah, I'm sure it's only non-generic for compatibility with .NET 1.x. It would be really nice to see it updated for .NET 2.0 (in fact the code would become shorter--the enumerator class could be dropped in favor of an iterator). > -----Original Message----- > From: Matt Sprague [mailto:mes...@gm...] > Sent: Wednesday, March 11, 2009 12:41 AM > To: swi...@li... > Subject: [Swig-user] C# - generic wrappers for std::vector<T> > > Why does the wrapper for std::vector<T> implement the non-generic > IEnumerable? It seems like it's fairly easy to modify the wrapper to > implement the generic IEnumerable. > > -Matt Sprague > > -------------------------------------------------------------------------- > ---- > Apps built with the Adobe(R) Flex(R) framework and Flex Builder(TM) are > powering Web 2.0 with engaging, cross-platform capabilities. Quickly and > easily build your RIAs with Flex Builder, the Eclipse(TM)based development > software that enables intelligent coding and step-through debugging. > Download the free 60 day trial. http://p.sf.net/sfu/www-adobe-com > _______________________________________________ > Swig-user mailing list > Swi...@li... > https://lists.sourceforge.net/lists/listinfo/swig-user |
From: William S F. <ws...@fu...> - 2009-03-11 21:40:50
|
Yup, compatibility with .NET 1 is the goal. You can always take a copy of std_vector.i and modify it to suite. William David Piepgrass wrote: > Yeah, I'm sure it's only non-generic for compatibility with .NET 1.x. It would be really nice to see it updated for .NET 2.0 (in fact the code would become shorter--the enumerator class could be dropped in favor of an iterator). > >> -----Original Message----- >> From: Matt Sprague [mailto:mes...@gm...] >> Sent: Wednesday, March 11, 2009 12:41 AM >> To: swi...@li... >> Subject: [Swig-user] C# - generic wrappers for std::vector<T> >> >> Why does the wrapper for std::vector<T> implement the non-generic >> IEnumerable? It seems like it's fairly easy to modify the wrapper to >> implement the generic IEnumerable. >> >> -Matt Sprague >> >> -------------------------------------------------------------------------- >> ---- >> Apps built with the Adobe(R) Flex(R) framework and Flex Builder(TM) are >> powering Web 2.0 with engaging, cross-platform capabilities. Quickly and >> easily build your RIAs with Flex Builder, the Eclipse(TM)based development >> software that enables intelligent coding and step-through debugging. >> Download the free 60 day trial. http://p.sf.net/sfu/www-adobe-com >> _______________________________________________ >> Swig-user mailing list >> Swi...@li... >> https://lists.sourceforge.net/lists/listinfo/swig-user > > ------------------------------------------------------------------------------ > Apps built with the Adobe(R) Flex(R) framework and Flex Builder(TM) are > powering Web 2.0 with engaging, cross-platform capabilities. Quickly and > easily build your RIAs with Flex Builder, the Eclipse(TM)based development > software that enables intelligent coding and step-through debugging. > Download the free 60 day trial. http://p.sf.net/sfu/www-adobe-com > _______________________________________________ > Swig-user mailing list > Swi...@li... > https://lists.sourceforge.net/lists/listinfo/swig-user > |
From: Matt S. <mes...@gm...> - 2009-03-11 22:27:39
|
I've modified std_vector.i for my own projects. However, given that v.4.0 of the framework is due out later this year, it might finally be time to look at adding support for generics to the std collections wrappers. -Matt On Wed, Mar 11, 2009 at 3:40 PM, William S Fulton <ws...@fu...> wrote: > Yup, compatibility with .NET 1 is the goal. You can always take a copy of > std_vector.i and modify it to suite. > > William > David Piepgrass wrote: >> >> Yeah, I'm sure it's only non-generic for compatibility with .NET 1.x. It >> would be really nice to see it updated for .NET 2.0 (in fact the code would >> become shorter--the enumerator class could be dropped in favor of an >> iterator). >> >>> -----Original Message----- >>> From: Matt Sprague [mailto:mes...@gm...] >>> Sent: Wednesday, March 11, 2009 12:41 AM >>> To: swi...@li... >>> Subject: [Swig-user] C# - generic wrappers for std::vector<T> >>> >>> Why does the wrapper for std::vector<T> implement the non-generic >>> IEnumerable? It seems like it's fairly easy to modify the wrapper to >>> implement the generic IEnumerable. >>> >>> -Matt Sprague >>> >>> >>> -------------------------------------------------------------------------- >>> ---- >>> Apps built with the Adobe(R) Flex(R) framework and Flex Builder(TM) are >>> powering Web 2.0 with engaging, cross-platform capabilities. Quickly and >>> easily build your RIAs with Flex Builder, the Eclipse(TM)based >>> development >>> software that enables intelligent coding and step-through debugging. >>> Download the free 60 day trial. http://p.sf.net/sfu/www-adobe-com >>> _______________________________________________ >>> Swig-user mailing list >>> Swi...@li... >>> https://lists.sourceforge.net/lists/listinfo/swig-user >> >> >> ------------------------------------------------------------------------------ >> Apps built with the Adobe(R) Flex(R) framework and Flex Builder(TM) are >> powering Web 2.0 with engaging, cross-platform capabilities. Quickly and >> easily build your RIAs with Flex Builder, the Eclipse(TM)based development >> software that enables intelligent coding and step-through debugging. >> Download the free 60 day trial. http://p.sf.net/sfu/www-adobe-com >> _______________________________________________ >> Swig-user mailing list >> Swi...@li... >> https://lists.sourceforge.net/lists/listinfo/swig-user >> > > |
From: William S F. <ws...@fu...> - 2009-03-11 23:14:00
|
We could define a preprocessor symbol for conditional C# compilation. Send a patch to std_vector.i and I'll take a look for future versions. William Matt Sprague wrote: > I've modified std_vector.i for my own projects. However, given that > v.4.0 of the framework is due out later this year, it might finally be > time to look at adding support for generics to the std collections > wrappers. > > -Matt > > On Wed, Mar 11, 2009 at 3:40 PM, William S Fulton > <ws...@fu...> wrote: >> Yup, compatibility with .NET 1 is the goal. You can always take a copy of >> std_vector.i and modify it to suite. >> >> William >> David Piepgrass wrote: >>> Yeah, I'm sure it's only non-generic for compatibility with .NET 1.x. It >>> would be really nice to see it updated for .NET 2.0 (in fact the code would >>> become shorter--the enumerator class could be dropped in favor of an >>> iterator). >>> >>>> -----Original Message----- >>>> From: Matt Sprague [mailto:mes...@gm...] >>>> Sent: Wednesday, March 11, 2009 12:41 AM >>>> To: swi...@li... >>>> Subject: [Swig-user] C# - generic wrappers for std::vector<T> >>>> >>>> Why does the wrapper for std::vector<T> implement the non-generic >>>> IEnumerable? It seems like it's fairly easy to modify the wrapper to >>>> implement the generic IEnumerable. >>>> >>>> -Matt Sprague >>>> >>>> >>>> -------------------------------------------------------------------------- >>>> ---- >>>> Apps built with the Adobe(R) Flex(R) framework and Flex Builder(TM) are >>>> powering Web 2.0 with engaging, cross-platform capabilities. Quickly and >>>> easily build your RIAs with Flex Builder, the Eclipse(TM)based >>>> development >>>> software that enables intelligent coding and step-through debugging. >>>> Download the free 60 day trial. http://p.sf.net/sfu/www-adobe-com >>>> _______________________________________________ >>>> Swig-user mailing list >>>> Swi...@li... >>>> https://lists.sourceforge.net/lists/listinfo/swig-user >>> >>> ------------------------------------------------------------------------------ >>> Apps built with the Adobe(R) Flex(R) framework and Flex Builder(TM) are >>> powering Web 2.0 with engaging, cross-platform capabilities. Quickly and >>> easily build your RIAs with Flex Builder, the Eclipse(TM)based development >>> software that enables intelligent coding and step-through debugging. >>> Download the free 60 day trial. http://p.sf.net/sfu/www-adobe-com >>> _______________________________________________ >>> Swig-user mailing list >>> Swi...@li... >>> https://lists.sourceforge.net/lists/listinfo/swig-user >>> >> > |
From: Mathieu M. <mat...@gm...> - 2009-03-13 10:20:32
|
awesome ! On Thu, Mar 12, 2009 at 12:13 AM, William S Fulton <ws...@fu...> wrote: > We could define a preprocessor symbol for conditional C# compilation. > Send a patch to std_vector.i and I'll take a look for future versions. > > William > > Matt Sprague wrote: >> I've modified std_vector.i for my own projects. However, given that >> v.4.0 of the framework is due out later this year, it might finally be >> time to look at adding support for generics to the std collections >> wrappers. >> >> -Matt >> >> On Wed, Mar 11, 2009 at 3:40 PM, William S Fulton >> <ws...@fu...> wrote: >>> Yup, compatibility with .NET 1 is the goal. You can always take a copy of >>> std_vector.i and modify it to suite. >>> >>> William >>> David Piepgrass wrote: >>>> Yeah, I'm sure it's only non-generic for compatibility with .NET 1.x. It >>>> would be really nice to see it updated for .NET 2.0 (in fact the code would >>>> become shorter--the enumerator class could be dropped in favor of an >>>> iterator). >>>> >>>>> -----Original Message----- >>>>> From: Matt Sprague [mailto:mes...@gm...] >>>>> Sent: Wednesday, March 11, 2009 12:41 AM >>>>> To: swi...@li... >>>>> Subject: [Swig-user] C# - generic wrappers for std::vector<T> >>>>> >>>>> Why does the wrapper for std::vector<T> implement the non-generic >>>>> IEnumerable? It seems like it's fairly easy to modify the wrapper to >>>>> implement the generic IEnumerable. >>>>> >>>>> -Matt Sprague >>>>> >>>>> >>>>> -------------------------------------------------------------------------- >>>>> ---- >>>>> Apps built with the Adobe(R) Flex(R) framework and Flex Builder(TM) are >>>>> powering Web 2.0 with engaging, cross-platform capabilities. Quickly and >>>>> easily build your RIAs with Flex Builder, the Eclipse(TM)based >>>>> development >>>>> software that enables intelligent coding and step-through debugging. >>>>> Download the free 60 day trial. http://p.sf.net/sfu/www-adobe-com >>>>> _______________________________________________ >>>>> Swig-user mailing list >>>>> Swi...@li... >>>>> https://lists.sourceforge.net/lists/listinfo/swig-user >>>> >>>> ------------------------------------------------------------------------------ >>>> Apps built with the Adobe(R) Flex(R) framework and Flex Builder(TM) are >>>> powering Web 2.0 with engaging, cross-platform capabilities. Quickly and >>>> easily build your RIAs with Flex Builder, the Eclipse(TM)based development >>>> software that enables intelligent coding and step-through debugging. >>>> Download the free 60 day trial. http://p.sf.net/sfu/www-adobe-com >>>> _______________________________________________ >>>> Swig-user mailing list >>>> Swi...@li... >>>> https://lists.sourceforge.net/lists/listinfo/swig-user >>>> >>> >> > > > ------------------------------------------------------------------------------ > Apps built with the Adobe(R) Flex(R) framework and Flex Builder(TM) are > powering Web 2.0 with engaging, cross-platform capabilities. Quickly and > easily build your RIAs with Flex Builder, the Eclipse(TM)based development > software that enables intelligent coding and step-through debugging. > Download the free 60 day trial. http://p.sf.net/sfu/www-adobe-com > _______________________________________________ > Swig-user mailing list > Swi...@li... > https://lists.sourceforge.net/lists/listinfo/swig-user > -- Mathieu |
From: David P. <dpi...@me...> - 2009-03-13 16:11:03
|
That's fine, just implementing IList<X> instead of just IEnumerable has significant benefits: - It works with LINQ - It can be passed to methods that expect IList<X>, ICollection<X> or IEnumerable<X> - The enumerator has higher performance (avoiding boxing & casting). Actually, you don't really need to implement IEnumerable<X> to achieve this, because IIRC an enumerator could return typed values to a foreach statement even in .NET 1.0; but the current implementation in SWIG enumerates objects. > Don't get too excited as generics for the std containers as you might > possibly envisage is not possible. You can't have a full generic C# > SwigVector<> wrapper for std::vector<T> as C# does not support > specialization, like C++ templates do, so the same logic for Java > generics applies, see > http://article.gmane.org/gmane.comp.programming.swig/9961/match=mapping+st > l+template+datatypes > for explanation. > > I'm waiting to see what Matt's generics modification for the IEnumerator > is though as I think there might be scope to convert the current type > safe enumerators in the wrapper into using generics. > > William > > Mathieu Malaterre wrote: > > awesome ! > > > > On Thu, Mar 12, 2009 at 12:13 AM, William S Fulton > > <ws...@fu...> wrote: > >> We could define a preprocessor symbol for conditional C# compilation. > >> Send a patch to std_vector.i and I'll take a look for future versions. > >> > >> William > >> > >> Matt Sprague wrote: > >>> I've modified std_vector.i for my own projects. However, given that > >>> v.4.0 of the framework is due out later this year, it might finally be > >>> time to look at adding support for generics to the std collections > >>> wrappers. > >>> > >>> -Matt > >>> > >>> On Wed, Mar 11, 2009 at 3:40 PM, William S Fulton > >>> <ws...@fu...> wrote: > >>>> Yup, compatibility with .NET 1 is the goal. You can always take a > copy of > >>>> std_vector.i and modify it to suite. > >>>> > >>>> William > >>>> David Piepgrass wrote: > >>>>> Yeah, I'm sure it's only non-generic for compatibility with .NET > 1.x. It > >>>>> would be really nice to see it updated for .NET 2.0 (in fact the > code would > >>>>> become shorter--the enumerator class could be dropped in favor of an > >>>>> iterator). > >>>>> > >>>>>> -----Original Message----- > >>>>>> From: Matt Sprague [mailto:mes...@gm...] > >>>>>> Sent: Wednesday, March 11, 2009 12:41 AM > >>>>>> To: swi...@li... > >>>>>> Subject: [Swig-user] C# - generic wrappers for std::vector<T> > >>>>>> > >>>>>> Why does the wrapper for std::vector<T> implement the non-generic > >>>>>> IEnumerable? It seems like it's fairly easy to modify the wrapper > to > >>>>>> implement the generic IEnumerable. > >>>>>> > >>>>>> -Matt Sprague > >>>>>> > >>>>>> > >>>>>> ------------------------------------------------------------------- > ------- > >>>>>> ---- > >>>>>> Apps built with the Adobe(R) Flex(R) framework and Flex Builder(TM) > are > >>>>>> powering Web 2.0 with engaging, cross-platform capabilities. > Quickly and > >>>>>> easily build your RIAs with Flex Builder, the Eclipse(TM)based > >>>>>> development > >>>>>> software that enables intelligent coding and step-through > debugging. > >>>>>> Download the free 60 day trial. http://p.sf.net/sfu/www-adobe-com > >>>>>> _______________________________________________ > >>>>>> Swig-user mailing list > >>>>>> Swi...@li... > >>>>>> https://lists.sourceforge.net/lists/listinfo/swig-user > >>>>> -------------------------------------------------------------------- > ---------- > >>>>> Apps built with the Adobe(R) Flex(R) framework and Flex Builder(TM) > are > >>>>> powering Web 2.0 with engaging, cross-platform capabilities. Quickly > and > >>>>> easily build your RIAs with Flex Builder, the Eclipse(TM)based > development > >>>>> software that enables intelligent coding and step-through debugging. > >>>>> Download the free 60 day trial. http://p.sf.net/sfu/www-adobe-com > >>>>> _______________________________________________ > >>>>> Swig-user mailing list > >>>>> Swi...@li... > >>>>> https://lists.sourceforge.net/lists/listinfo/swig-user > >>>>> > >> > >> ----------------------------------------------------------------------- > ------- > >> Apps built with the Adobe(R) Flex(R) framework and Flex Builder(TM) are > >> powering Web 2.0 with engaging, cross-platform capabilities. Quickly > and > >> easily build your RIAs with Flex Builder, the Eclipse(TM)based > development > >> software that enables intelligent coding and step-through debugging. > >> Download the free 60 day trial. http://p.sf.net/sfu/www-adobe-com > >> _______________________________________________ > >> Swig-user mailing list > >> Swi...@li... > >> https://lists.sourceforge.net/lists/listinfo/swig-user > >> > > > > > > > > > -------------------------------------------------------------------------- > ---- > Apps built with the Adobe(R) Flex(R) framework and Flex Builder(TM) are > powering Web 2.0 with engaging, cross-platform capabilities. Quickly and > easily build your RIAs with Flex Builder, the Eclipse(TM)based development > software that enables intelligent coding and step-through debugging. > Download the free 60 day trial. http://p.sf.net/sfu/www-adobe-com > _______________________________________________ > Swig-user mailing list > Swi...@li... > https://lists.sourceforge.net/lists/listinfo/swig-user |
From: David P. <dpi...@me...> - 2009-03-20 23:59:16
|
> I've made changes to implement IEnumerable<> rather than IList<> as > IList<> ultimately requires the C++ operator== to be available, which it > often isn't. You can already put SWIG wrappers in List<T> objects, so it's kind of disingenuous to imply IList<T> can't be supported. And List<T> doesn't use operator==, which is a statically bound call and therefore not callable from generic classes. Instead it uses EqualityComparer<T>.Default, I believe, which must use Equals(). The most important features of IList<T> such as Add, Remove, Clear, and this[index] do not use an equality test, so I strongly encourage you to reconsider. Besides, any SWIG user could (and IMO, should) override Equals(object) and operator==() as I have done. My approach is something like this, except altered to be Compact Framework compatible: %typemap(csclassmodifiers) SWIGTYPE "public partial class" %typemap(csclassmodifiers) SWIGTYPE *, SWIGTYPE &, SWIGTYPE [], SWIGTYPE (CLASS::*) "public partial struct" //////////////////////////////////////////////////////////////////////////// // Implement Equals() and GetHashCode() on all wrapper classes. The same C++ // object may be represented by multiple instances of the proxy class, so we // need to change these functions so that two different instances of the proxy // class that point to the same C++ object are considered equal and have the // same hash code. At the same time, improve code sharing by putting these // functions, getCPtr() and swigCPtr in a common base class. // // Put Equals() and GetHashCode() in a base class ("CppWrapper") so that they // can be replaced, if desired, in a derived class. %pragma(csharp) imclassimports=%{ using System; using System.Runtime.InteropServices; using System.Drawing; public class CppWrapper { protected HandleRef swigCPtr; public CppWrapper(IntPtr cPtr) { swigCPtr = new HandleRef(this, cPtr); } protected internal static IntPtr getCPtr(CppWrapper obj) { return object.ReferenceEquals(obj, null) ? IntPtr.Zero : (IntPtr)obj.swigCPtr; } public override bool Equals(object other_) { CppWrapper other = other_ as CppWrapper; return getCPtr(other) == swigCPtr; } public override int GetHashCode() { return swigCPtr.ToInt32(); } public static bool operator!=(CppWrapper a, CppWrapper b) { return getCPtr(a) != getCPtr(b); } public static bool operator==(CppWrapper a, CppWrapper b) { return getCPtr(a) == getCPtr(b); } } %} %typemap(csbase) SWIGTYPE "CppWrapper" %typemap(csbase) SWIGTYPE *, SWIGTYPE &, SWIGTYPE [], SWIGTYPE (CLASS::*) "" // SWIG gives this absurd warning for derived classes: "Warning for // DerivedClass proxy: Base CppWrapper ignored. Multiple inheritance is not // supported in C#." Workaround: suppress that warning universally %warnfilter(SWIGWARN_CSHARP_MULTIPLE_INHERITANCE); // Normal wrappers (for defined types) use this code %typemap(csbody, noblock=1) SWIGTYPE { // protected bool swigCMemOwn; protected internal $csclassname(IntPtr cPtr, bool cMemoryOwn) : base(cPtr) { if (!(swigCMemOwn = cMemoryOwn)) GC.SuppressFinalize(this); } } // Wrappers for unknown types (e.g. SWIGTYPE_p_int) use this code %typemap(csbody, noblock=1) SWIGTYPE *, SWIGTYPE &, SWIGTYPE [] { // protected HandleRef swigCPtr; internal $csclassname(IntPtr cPtr, bool futureUse) { swigCPtr = new HandleRef(this, cPtr); } internal static HandleRef getCPtr(CppWrapper obj) { return (obj == null) ? IntPtr.Zero : obj.swigCPtr; } } // Derived proxy classes use this code // In my wrappers there is no reason to call back into C++ to do an upcast // (and SWIG doesn't support multiple inheritance anyway), so I removed that // code from here. %typemap(csbody_derived) SWIGTYPE %{ //private HandleRef swigCPtr; internal $csclassname(IntPtr cPtr, bool cMemoryOwn) : base(cPtr, cMemoryOwn) { // : base($imclassname.$csclassnameUpcast(cPtr), cMemoryOwn) { //swigCPtr = new HandleRef(this, cPtr); } //internal static HandleRef getCPtr($csclassname obj) { // return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr; //} %} ------------------------------------------------------------------- > Please try it out in the next day, just use the latest std_vector.i by > putting it in whichever version of SWIG you have. Get it from: > http://swig.svn.sourceforge.net/viewvc/swig/trunk/Lib/csharp/std_vector.i? > view=log OK, I'll try to remember to try it. I can't try it until Monday though. > Are you saying that the current enumerator implementation, which as you > say uses objects, can be improved performance-wise? Should we replace > storing as 'object' with the real collection type? It'll need a slight > rewrite though as casting null to primitive types (if collection type is > primitive) doesn't work. Yes, you'll get higher performance using the real collection type, especially if the real collection type is something simple like int. I think it's legal to use default(xyz) instead of null, e.g. default(int) is 0 and default(string) is null. |
From: David P. <dpi...@me...> - 2009-03-21 00:27:08
|
> > Please try it out in the next day, just use the latest std_vector.i by > > putting it in whichever version of SWIG you have. Get it from: > > > http://swig.svn.sourceforge.net/viewvc/swig/trunk/Lib/csharp/std_vector.i? > > view=log > > OK, I'll try to remember to try it. I can't try it until Monday though. Oops, I didn't notice that I was replying to a 2-day old message. I need some rest! Good night! |
From: David P. <dpi...@me...> - 2009-04-03 00:14:17
|
> > public override int GetHashCode() { > > return swigCPtr.ToInt32(); > > } > XOR high and low bits as suggested in the Object.GetHashCode docs would > be better - > http://msdn.microsoft.com/en-us/library/system.object.gethashcode(VS.80).aspx > > (for 64 bit pointers). If Microsoft follows its own advice, you should be able to simply call swigCPtr.GetHashCode() and it would hash the high and low words for you. But documentation of HandleRef.GetHashCode appears not to have been written. I wouldn't worry about it, because I'll bet there isn't a lot of variation in the high-order 32 bits of a 64-bit pointer. Besides, aren't most people still using 32 bit processes? > Having a single swigCPtr in the inheritance hierarchy is dangerous, see > comments below. Yeah, it's dangerous in general, I know, but it's safe for me personally because I don't use MI in code wrapped by SWIG. > > %typemap(csbase) SWIGTYPE *, SWIGTYPE &, SWIGTYPE [], SWIGTYPE > (CLASS::*) "" > > // SWIG gives this absurd warning for derived classes: "Warning for > > // DerivedClass proxy: Base CppWrapper ignored. Multiple inheritance is > not > > // supported in C#." Workaround: suppress that warning universally > > %warnfilter(SWIGWARN_CSHARP_MULTIPLE_INHERITANCE); > > Didn't we fix this by providing the 'replace' attribute - Bug #1794247? > If not, please lodge a new bug including a small use case. I've seen you > post your typemaps a few times which is great, but would prefer up to > date code if doing so again so as to not mislead future 'googlers'. I reviewed the bug at http://sourceforge.net/tracker/?func=detail&atid=101645&aid=1794247&group_id=1645 and I do not understand what the 'replace' attribute is good for; therefore I do not use it. > > // Normal wrappers (for defined types) use this code > > %typemap(csbody, noblock=1) SWIGTYPE > > { // > > protected bool swigCMemOwn; > > protected internal $csclassname(IntPtr cPtr, bool cMemoryOwn) : > base(cPtr) { > > if (!(swigCMemOwn = cMemoryOwn)) > > GC.SuppressFinalize(this); > > } > This is a neat performance trick I've not seen before which I thought > might be useful for the default typemaps. But after some pondering I > think it is too risky to put into the default SWIG typemaps as it is > possible that some users customisations will set swigCMemOwn to true > after the constructor is called. I'd suggest making swigCMemOwn > readonly to future proof your code with a compilation error... once > you've done that I think you'll find that you could even get rid of the > swigCMemOwn flag altogether. Interesting idea, eliminating swigCMemOwn. One very minor problem: any shmuck can call GC.ReRegisterForFinalize on the object. Anyway, it might be interesting to make swigCMemOwn readonly and then wait to see if anyone posts a regression bug report. > Could I ask you to add in a big DANGER sign in your comments here if > you are going to post this onto the internet again as you are relying on > behaviour that is not guaranteed in the C++ standard and is liable to > subtle, hard to track bugs, particularly so as you have suppressed > SWIGWARN_CSHARP_MULTIPLE_INHERITANCE. Well, I only suppressed the warning because it's spurious. Anyway, here's my new comment: // Note: In my wrappers there is no reason to call back into C++ to do an // upcast (and SWIG doesn't support multiple inheritance anyway), so I // removed that code from here. *** DANGER ***: this violates the letter // of the C++ standard, and may fail horribly (with a segfault or // something) if you use this particular typemap while wrapping classes // that use virtual inheritance or multiple inheritance. > The idea of overriding Equals and GetHashCode and overloading operator== > makes sense as it provides reference equals on the C++ instance level > rather than on C# instances and I'm thinking of putting this as a > default into SWIG. However, using a single base class implementation of > this is incorrect and instead I'd generate the methods into every proxy > class. I don't think that's necessary. If the base-class value of swigCPtr compares equal in two different proxy objects, surely the two proxies point to the same object? > With regard to using the C++ operator==, the advice given in the MSDN > links above says: "Consider overriding Equals on a reference type if the > semantics of the type are based on the fact that the type represents > some value(s)". Surely, if there is a C++ operator== the advice then > applies and we should be using value equality. If say we are wrapping > std::vector<T> where T is a class (not a pointer to a class), then using > reference equals is just plain wrong as we are storing the object by > value, not reference/pointer. If we are wrapping > std::vector<T*> or std::vector<T&> then implementing reference equality > makes sense and we could modify the specializations in std_vector.i to > do this. Ahh, hmm. I see your point. As it happens, I have been using SWIG to wrap vectors of VALUES like e.g. vector<Point> (which comes out as a list of System.Drawing.Point on the C# side) and vector<int>. Looking at the matter through that lens, I would like to have the IList<T> interface available in cases like that. I strongly agree that SWIG ought to detect equality of two C pointers by default. It's better to provide a reasonable default (equality of C pointers) than the unreasonable default SWIG has now (reference equality of proxy objects). Equality of C pointers is good enough for many, if not most cases... but vector<T> where T is a SWIG-wrapped type is not one of those cases :( |
From: David P. <dpi...@me...> - 2009-04-16 21:21:50
|
> David Piepgrass wrote: > >>> public override int GetHashCode() { > >>> return swigCPtr.ToInt32(); > >>> } > >> XOR high and low bits as suggested in the Object.GetHashCode docs would > >> be better - > >> http://msdn.microsoft.com/en- > us/library/system.object.gethashcode(VS.80).aspx > >> > >> (for 64 bit pointers). > > > > If Microsoft follows its own advice, you should be able to simply call > swigCPtr.GetHashCode() and it would hash the high and low words for you. > But documentation of HandleRef.GetHashCode appears not to have been > written. > > > > I wouldn't worry about it, because I'll bet there isn't a lot of > variation in the high-order 32 bits of a 64-bit pointer. Besides, aren't > most people still using 32 bit processes? > > > There are the odd few bravodos using 64 bit Windows. It is a bit > nick-pickety, but we need to cover these corner cases if distributed > with SWIG, but sure if you aren't interested in 64 bit then it makes no > odds. Whether the OS is 64-bit doesn't really matter--what matters is whether the process is 64-bit. If few people are using a 64-bit OS, then fewer still are using 64-bit processes. Anyway, my other point is still valid: if the high bits rarely vary then they are not an important part of the hash code. Put another way: given any two 64-bit addresses, often the high 32 bits are the same. But if the high bits are not the same, then the low bits are almost certainly not the same either. > > I reviewed the bug at > > > http://sourceforge.net/tracker/?func=detail&atid=101645&aid=1794247&group_ > id=1645 > > > > and I do not understand what the 'replace' attribute is good for; > therefore I do not use it. > > > See the entry dated 10/13/2006 in the CHANGES file, and the > documentation at > http://www.swig.org/Doc1.3/Java.html#java_code_typemaps. The following > shows how you can use it (taken from > Examples/test-suite/inherit_target_language.i), where TargetLanguageBase > is any C# class: > > %typemap(csbase, replace="1") MultipleDerived2 "TargetLanguageBase" > struct MBase1a { virtual ~MBase1a() {} virtual void a() {} }; > struct MBase2b { virtual ~MBase2b() {} virtual void d() {} }; > struct MultipleDerived2 : MBase1a, MBase2b {}; > > The base class for MultipleDerived2 is set to be TargetLanguageBase. The > multiple inheritance warning is suppressed for MultipleDerived2 because > the 'replace' flag is set. So TargetLanguageBase is basically a user-defined, manually-written wrapper to replace the one that SWIG would have generated but doesn't know how to. Right? Well, this use case is unrelated to the way *I* use the csbase typemap. If I were to use the 'replace' flag, it would totally bork my proxy classes. You must understand, I am only using csbase as a way to make my proxy classes more efficient, by sharing common code between them instead of inserting identical methods into every single one. Of course, I only want to give this common base class to classes that have NO base class in C++. Put another way: by default, the ultimate base class of all SWIG proxies is System.Object. I am using csbase to change the ultimate base class to something else. Fortunately, SWIG supports this. Unfortunately, it issues a meaningless warning that I have to suppress. Capice? > > // Note: In my wrappers there is no reason to call back into C++ to do > an > > // upcast (and SWIG doesn't support multiple inheritance anyway), so I > > // removed that code from here. *** DANGER ***: this violates the letter > > // of the C++ standard, and may fail horribly (with a segfault or > > // something) if you use this particular typemap while wrapping classes > > // that use virtual inheritance or multiple inheritance. > > > I'm happy now ;) :D > > >> The idea of overriding Equals and GetHashCode and overloading > operator== > >> makes sense as it provides reference equals on the C++ instance level > >> rather than on C# instances and I'm thinking of putting this as a > >> default into SWIG. However, using a single base class implementation of > >> this is incorrect and instead I'd generate the methods into every proxy > >> class. > > > > I don't think that's necessary. If the base-class value of swigCPtr > compares equal in two different proxy objects, surely the two proxies > point to the same object? > Sure, but SWIG doesn't use this common base class paradigm, which is > frowned upon in some circles. It therefore would need to be generated > into each class which is at the root of any inheritance hierarchy. That's what I meant: If the base classes are equal, then surely all derived classes are equal too. P.S. what's not to like about my 'common base class paradigm'? |
From: David P. <dpi...@me...> - 2009-04-21 15:05:33
|
> >> %typemap(csbase, replace="1") MultipleDerived2 "TargetLanguageBase" > >> struct MBase1a { virtual ~MBase1a() {} virtual void a() {} }; > >> struct MBase2b { virtual ~MBase2b() {} virtual void d() {} }; > >> struct MultipleDerived2 : MBase1a, MBase2b {}; > >> > >> The base class for MultipleDerived2 is set to be TargetLanguageBase. > The > >> multiple inheritance warning is suppressed for MultipleDerived2 because > >> the 'replace' flag is set. > > > > So TargetLanguageBase is basically a user-defined, manually-written > wrapper to replace the one that SWIG would have generated but doesn't know > how to. Right? Well, this use case is unrelated to the way *I* use the > csbase typemap. If I were to use the 'replace' flag, it would totally bork > my proxy classes. > > > > You must understand, I am only using csbase as a way to make my proxy > classes more efficient, by sharing common code between them instead of > inserting identical methods into every single one. Of course, I only want > to give this common base class to classes that have NO base class in C++. > > > > Put another way: by default, the ultimate base class of all SWIG proxies > is System.Object. I am using csbase to change the ultimate base class to > something else. Fortunately, SWIG supports this. Unfortunately, it issues > a meaningless warning that I have to suppress. Capice? > It is clear *what* you are trying to achieve, but I'm afraid I do not > see *how* you are getting this warning given what you are trying to > achieve. Please give an example. In what way does the 'replace' > attribute bork your proxy classes and what exactly do you mean by this? > > William Well suppose I use csbase as follows... %typemap(csbase) SWIGTYPE "CppWrapper" %pragma(csharp) imclassimports=%{ ... public class CppWrapper { // code to share between all SWIG objects ... public override bool Equals(object other_) { CppWrapper other = other_ as CppWrapper; return getCPtr(other) == swigCPtr; } public override int GetHashCode() { return swigCPtr.ToInt32(); } ... } %} And suppose I define classes A and B: class A { void F(); }; class B : public A { void G(); }; Then I get "Warning for B proxy: Base CppWrapper ignored. Multiple inheritance is not supported in C#." However, if I were to use replace=1 with csbase: %typemap(csbase, replace="1") SWIGTYPE "CppWrapper" Then instead of getting C# proxy classes class A : CppBase { ... void F() { ... } } class B : A { ... void G() { ... } } I would get class A : CppBase { ... void F() { ... } } class B : CppBase { ... void G() { ... } } Off the top of my head this borks B in two ways: 1. The user cannot call A::F() on a B object 2. The user cannot cast B to A. Clear enough yet? |
From: William S F. <ws...@fu...> - 2009-04-29 17:59:49
|
David Piepgrass wrote: > Well suppose I use csbase as follows... > > %typemap(csbase) SWIGTYPE "CppWrapper" > %pragma(csharp) imclassimports=%{ > ... > public class CppWrapper { > // code to share between all SWIG objects > ... > public override bool Equals(object other_) { > CppWrapper other = other_ as CppWrapper; > return getCPtr(other) == swigCPtr; > } > public override int GetHashCode() { > return swigCPtr.ToInt32(); > } > ... > } > %} > > And suppose I define classes A and B: > > class A { void F(); }; > class B : public A { void G(); }; > > Then I get "Warning for B proxy: Base CppWrapper ignored. Multiple inheritance is not supported in C#." > > However, if I were to use replace=1 with csbase: > > %typemap(csbase, replace="1") SWIGTYPE "CppWrapper" > > Then instead of getting C# proxy classes > > class A : CppBase { ... void F() { ... } } > class B : A { ... void G() { ... } } > > I would get > > class A : CppBase { ... void F() { ... } } > class B : CppBase { ... void G() { ... } } > > Off the top of my head this borks B in two ways: > > 1. The user cannot call A::F() on a B object > 2. The user cannot cast B to A. > > Clear enough yet? > Yup, what is clear now is you are using the generic 'SWIGTYPE' typemap. If you target specific classes in the typemap, then you wouldn't have this problem as you wouldn't use the typemap for derived classes. Given that you want a general solution using SWIGTYPE as the typemap type, the best solution I can think of is to have a new attribute in the typemap that would not apply to derived classes. Now you can use: %typemap(csbase, notderived="1") SWIGTYPE "CppWrapper" instead. The typemap will not apply to B and no warning messages are issued. Hope that meets your requirements, get it from svn. William |
From: William S F. <ws...@fu...> - 2009-03-13 10:55:10
|
Don't get too excited as generics for the std containers as you might possibly envisage is not possible. You can't have a full generic C# SwigVector<> wrapper for std::vector<T> as C# does not support specialization, like C++ templates do, so the same logic for Java generics applies, see http://article.gmane.org/gmane.comp.programming.swig/9961/match=mapping+stl+template+datatypes for explanation. I'm waiting to see what Matt's generics modification for the IEnumerator is though as I think there might be scope to convert the current type safe enumerators in the wrapper into using generics. William Mathieu Malaterre wrote: > awesome ! > > On Thu, Mar 12, 2009 at 12:13 AM, William S Fulton > <ws...@fu...> wrote: >> We could define a preprocessor symbol for conditional C# compilation. >> Send a patch to std_vector.i and I'll take a look for future versions. >> >> William >> >> Matt Sprague wrote: >>> I've modified std_vector.i for my own projects. However, given that >>> v.4.0 of the framework is due out later this year, it might finally be >>> time to look at adding support for generics to the std collections >>> wrappers. >>> >>> -Matt >>> >>> On Wed, Mar 11, 2009 at 3:40 PM, William S Fulton >>> <ws...@fu...> wrote: >>>> Yup, compatibility with .NET 1 is the goal. You can always take a copy of >>>> std_vector.i and modify it to suite. >>>> >>>> William >>>> David Piepgrass wrote: >>>>> Yeah, I'm sure it's only non-generic for compatibility with .NET 1.x. It >>>>> would be really nice to see it updated for .NET 2.0 (in fact the code would >>>>> become shorter--the enumerator class could be dropped in favor of an >>>>> iterator). >>>>> >>>>>> -----Original Message----- >>>>>> From: Matt Sprague [mailto:mes...@gm...] >>>>>> Sent: Wednesday, March 11, 2009 12:41 AM >>>>>> To: swi...@li... >>>>>> Subject: [Swig-user] C# - generic wrappers for std::vector<T> >>>>>> >>>>>> Why does the wrapper for std::vector<T> implement the non-generic >>>>>> IEnumerable? It seems like it's fairly easy to modify the wrapper to >>>>>> implement the generic IEnumerable. >>>>>> >>>>>> -Matt Sprague >>>>>> >>>>>> >>>>>> -------------------------------------------------------------------------- >>>>>> ---- >>>>>> Apps built with the Adobe(R) Flex(R) framework and Flex Builder(TM) are >>>>>> powering Web 2.0 with engaging, cross-platform capabilities. Quickly and >>>>>> easily build your RIAs with Flex Builder, the Eclipse(TM)based >>>>>> development >>>>>> software that enables intelligent coding and step-through debugging. >>>>>> Download the free 60 day trial. http://p.sf.net/sfu/www-adobe-com >>>>>> _______________________________________________ >>>>>> Swig-user mailing list >>>>>> Swi...@li... >>>>>> https://lists.sourceforge.net/lists/listinfo/swig-user >>>>> ------------------------------------------------------------------------------ >>>>> Apps built with the Adobe(R) Flex(R) framework and Flex Builder(TM) are >>>>> powering Web 2.0 with engaging, cross-platform capabilities. Quickly and >>>>> easily build your RIAs with Flex Builder, the Eclipse(TM)based development >>>>> software that enables intelligent coding and step-through debugging. >>>>> Download the free 60 day trial. http://p.sf.net/sfu/www-adobe-com >>>>> _______________________________________________ >>>>> Swig-user mailing list >>>>> Swi...@li... >>>>> https://lists.sourceforge.net/lists/listinfo/swig-user >>>>> >> >> ------------------------------------------------------------------------------ >> Apps built with the Adobe(R) Flex(R) framework and Flex Builder(TM) are >> powering Web 2.0 with engaging, cross-platform capabilities. Quickly and >> easily build your RIAs with Flex Builder, the Eclipse(TM)based development >> software that enables intelligent coding and step-through debugging. >> Download the free 60 day trial. http://p.sf.net/sfu/www-adobe-com >> _______________________________________________ >> Swig-user mailing list >> Swi...@li... >> https://lists.sourceforge.net/lists/listinfo/swig-user >> > > > |
From: William S F. <ws...@fu...> - 2009-03-19 00:21:56
|
I've made changes to implement IEnumerable<> rather than IList<> as IList<> ultimately requires the C++ operator== to be available, which it often isn't. It would be possible to derive from IList<> for std::vector<T> where T is primitive, pointer etc, but not a class/struct by default. So to keep consistency for all types I have not done this. The IEnumerable<> is what is required for LINQ and so that works nicely now. Please try it out in the next day, just use the latest std_vector.i by putting it in whichever version of SWIG you have. Get it from: http://swig.svn.sourceforge.net/viewvc/swig/trunk/Lib/csharp/std_vector.i?view=log I want to make a new release of SWIG in two days, so testing before then is appreciated. Note that I have decided to make a change so that .NET 2 is required by default for std::vector wrappers, but can easily be changed for .NET 1 via a compiler define ... see notes in the std_vector.i file. Are you saying that the current enumerator implementation, which as you say uses objects, can be improved performance-wise? Should we replace storing as 'object' with the real collection type? It'll need a slight rewrite though as casting null to primitive types (if collection type is primitive) doesn't work. William David Piepgrass wrote: > That's fine, just implementing IList<X> instead of just IEnumerable has significant benefits: > > - It works with LINQ > - It can be passed to methods that expect IList<X>, ICollection<X> or IEnumerable<X> > - The enumerator has higher performance (avoiding boxing & casting). Actually, you don't really need to implement IEnumerable<X> to achieve this, because IIRC an enumerator could return typed values to a foreach statement even in .NET 1.0; but the current implementation in SWIG enumerates objects. > >> Don't get too excited as generics for the std containers as you might >> possibly envisage is not possible. You can't have a full generic C# >> SwigVector<> wrapper for std::vector<T> as C# does not support >> specialization, like C++ templates do, so the same logic for Java >> generics applies, see >> http://article.gmane.org/gmane.comp.programming.swig/9961/match=mapping+st >> l+template+datatypes >> for explanation. >> >> I'm waiting to see what Matt's generics modification for the IEnumerator >> is though as I think there might be scope to convert the current type >> safe enumerators in the wrapper into using generics. >> >> William >> >> Mathieu Malaterre wrote: >>> awesome ! >>> >>> On Thu, Mar 12, 2009 at 12:13 AM, William S Fulton >>> <ws...@fu...> wrote: >>>> We could define a preprocessor symbol for conditional C# compilation. >>>> Send a patch to std_vector.i and I'll take a look for future versions. >>>> >>>> William >>>> >>>> Matt Sprague wrote: >>>>> I've modified std_vector.i for my own projects. However, given that >>>>> v.4.0 of the framework is due out later this year, it might finally be >>>>> time to look at adding support for generics to the std collections >>>>> wrappers. >>>>> >>>>> -Matt >>>>> >>>>> On Wed, Mar 11, 2009 at 3:40 PM, William S Fulton >>>>> <ws...@fu...> wrote: >>>>>> Yup, compatibility with .NET 1 is the goal. You can always take a >> copy of >>>>>> std_vector.i and modify it to suite. >>>>>> >>>>>> William >>>>>> David Piepgrass wrote: >>>>>>> Yeah, I'm sure it's only non-generic for compatibility with .NET >> 1.x. It >>>>>>> would be really nice to see it updated for .NET 2.0 (in fact the >> code would >>>>>>> become shorter--the enumerator class could be dropped in favor of an >>>>>>> iterator). >>>>>>> >>>>>>>> -----Original Message----- >>>>>>>> From: Matt Sprague [mailto:mes...@gm...] >>>>>>>> Sent: Wednesday, March 11, 2009 12:41 AM >>>>>>>> To: swi...@li... >>>>>>>> Subject: [Swig-user] C# - generic wrappers for std::vector<T> >>>>>>>> >>>>>>>> Why does the wrapper for std::vector<T> implement the non-generic >>>>>>>> IEnumerable? It seems like it's fairly easy to modify the wrapper >> to >>>>>>>> implement the generic IEnumerable. >>>>>>>> >>>>>>>> -Matt Sprague >>>>>>>> >>>>>>>> >>>>>>>> ------------------------------------------------------------------- >> ------- >>>>>>>> ---- >>>>>>>> Apps built with the Adobe(R) Flex(R) framework and Flex Builder(TM) >> are >>>>>>>> powering Web 2.0 with engaging, cross-platform capabilities. >> Quickly and >>>>>>>> easily build your RIAs with Flex Builder, the Eclipse(TM)based >>>>>>>> development >>>>>>>> software that enables intelligent coding and step-through >> debugging. >>>>>>>> Download the free 60 day trial. http://p.sf.net/sfu/www-adobe-com >>>>>>>> _______________________________________________ >>>>>>>> Swig-user mailing list >>>>>>>> Swi...@li... >>>>>>>> https://lists.sourceforge.net/lists/listinfo/swig-user >>>>>>> -------------------------------------------------------------------- >> ---------- >>>>>>> Apps built with the Adobe(R) Flex(R) framework and Flex Builder(TM) >> are >>>>>>> powering Web 2.0 with engaging, cross-platform capabilities. Quickly >> and >>>>>>> easily build your RIAs with Flex Builder, the Eclipse(TM)based >> development >>>>>>> software that enables intelligent coding and step-through debugging. >>>>>>> Download the free 60 day trial. http://p.sf.net/sfu/www-adobe-com >>>>>>> _______________________________________________ >>>>>>> Swig-user mailing list >>>>>>> Swi...@li... >>>>>>> https://lists.sourceforge.net/lists/listinfo/swig-user >>>>>>> >>>> ----------------------------------------------------------------------- >> ------- >>>> Apps built with the Adobe(R) Flex(R) framework and Flex Builder(TM) are >>>> powering Web 2.0 with engaging, cross-platform capabilities. Quickly >> and >>>> easily build your RIAs with Flex Builder, the Eclipse(TM)based >> development >>>> software that enables intelligent coding and step-through debugging. >>>> Download the free 60 day trial. http://p.sf.net/sfu/www-adobe-com >>>> _______________________________________________ >>>> Swig-user mailing list >>>> Swi...@li... >>>> https://lists.sourceforge.net/lists/listinfo/swig-user >>>> >>> >>> >> >> -------------------------------------------------------------------------- >> ---- >> Apps built with the Adobe(R) Flex(R) framework and Flex Builder(TM) are >> powering Web 2.0 with engaging, cross-platform capabilities. Quickly and >> easily build your RIAs with Flex Builder, the Eclipse(TM)based development >> software that enables intelligent coding and step-through debugging. >> Download the free 60 day trial. http://p.sf.net/sfu/www-adobe-com >> _______________________________________________ >> Swig-user mailing list >> Swi...@li... >> https://lists.sourceforge.net/lists/listinfo/swig-user > |
From: William S F. <ws...@fu...> - 2009-04-01 21:46:39
|
David Piepgrass wrote: >> I've made changes to implement IEnumerable<> rather than IList<> as >> IList<> ultimately requires the C++ operator== to be available, which it >> often isn't. > > You can already put SWIG wrappers in List<T> objects, so it's kind of disingenuous to imply IList<T> can't be supported. And List<T> doesn't use operator==, which is a statically bound call and therefore not callable from generic classes. Instead it uses EqualityComparer<T>.Default, I believe, which must use Equals(). > > The most important features of IList<T> such as Add, Remove, Clear, and this[index] do not use an equality test, so I strongly encourage you to reconsider. But in order to implement an interface, all the methods must be implemented. IList<T> requires the IndexOf and Contains methods, which in turn require the C++ std::find, which in turn requires a C++ operator==. This is because we are using value equality, not reference equality, see my comments at the end. Basically I don't won't to put in dependencies that will result in non-compileable code most of the time. Note that although, the wrappers don't implement IList<>, they do implement most of the methods that IList<> requires. The ones omitted are the ones that rely on equality. > > Besides, any SWIG user could (and IMO, should) override Equals(object) and operator==() as I have done. My approach is something like this, except altered to be Compact Framework compatible: > > %typemap(csclassmodifiers) SWIGTYPE "public partial class" > %typemap(csclassmodifiers) SWIGTYPE *, SWIGTYPE &, SWIGTYPE [], SWIGTYPE (CLASS::*) "public partial struct" > > //////////////////////////////////////////////////////////////////////////// > // Implement Equals() and GetHashCode() on all wrapper classes. The same C++ > // object may be represented by multiple instances of the proxy class, so we > // need to change these functions so that two different instances of the proxy > // class that point to the same C++ object are considered equal and have the > // same hash code. At the same time, improve code sharing by putting these > // functions, getCPtr() and swigCPtr in a common base class. > // > // Put Equals() and GetHashCode() in a base class ("CppWrapper") so that they > // can be replaced, if desired, in a derived class. > %pragma(csharp) imclassimports=%{ > using System; > using System.Runtime.InteropServices; > using System.Drawing; > > public class CppWrapper > { > protected HandleRef swigCPtr; > > public CppWrapper(IntPtr cPtr) > { swigCPtr = new HandleRef(this, cPtr); } > > protected internal static IntPtr getCPtr(CppWrapper obj) { > return object.ReferenceEquals(obj, null) ? IntPtr.Zero : (IntPtr)obj.swigCPtr; > } > public override bool Equals(object other_) { > CppWrapper other = other_ as CppWrapper; > return getCPtr(other) == swigCPtr; > } This implementation of Equals needs modifying to meet the conditions as stated in the Object.Equals documentation - http://msdn.microsoft.com/en-us/library/bsc2ak47(VS.80).aspx and "Guidelines for Overloading Equals() and Operator == (C# Programming Guide)" - http://msdn.microsoft.com/en-us/library/ms173147(VS.80).aspx. > public override int GetHashCode() { > return swigCPtr.ToInt32(); > } XOR high and low bits as suggested in the Object.GetHashCode docs would be better - http://msdn.microsoft.com/en-us/library/system.object.gethashcode(VS.80).aspx (for 64 bit pointers). > public static bool operator!=(CppWrapper a, CppWrapper b) > { return getCPtr(a) != getCPtr(b); } > public static bool operator==(CppWrapper a, CppWrapper b) > { return getCPtr(a) == getCPtr(b); } > } > %} > %typemap(csbase) SWIGTYPE "CppWrapper" Having a single swigCPtr in the inheritance hierarchy is dangerous, see comments below. > %typemap(csbase) SWIGTYPE *, SWIGTYPE &, SWIGTYPE [], SWIGTYPE (CLASS::*) "" > // SWIG gives this absurd warning for derived classes: "Warning for > // DerivedClass proxy: Base CppWrapper ignored. Multiple inheritance is not > // supported in C#." Workaround: suppress that warning universally > %warnfilter(SWIGWARN_CSHARP_MULTIPLE_INHERITANCE); Didn't we fix this by providing the 'replace' attribute - Bug #1794247? If not, please lodge a new bug including a small use case. I've seen you post your typemaps a few times which is great, but would prefer up to date code if doing so again so as to not mislead future 'googlers'. > // Normal wrappers (for defined types) use this code > %typemap(csbody, noblock=1) SWIGTYPE > { // > protected bool swigCMemOwn; > protected internal $csclassname(IntPtr cPtr, bool cMemoryOwn) : base(cPtr) { > if (!(swigCMemOwn = cMemoryOwn)) > GC.SuppressFinalize(this); > } This is a neat performance trick I've not seen before which I thought might be useful for the default typemaps. But after some pondering I think it is too risky to put into the default SWIG typemaps as it is possible that some users customisations will set swigCMemOwn to true after the constructor is called. I'd suggest making swigCMemOwn readonly to future proof your code with a compilation error... once you've done that I think you'll find that you could even get rid of the swigCMemOwn flag altogether. > } > > // Wrappers for unknown types (e.g. SWIGTYPE_p_int) use this code > %typemap(csbody, noblock=1) SWIGTYPE *, SWIGTYPE &, SWIGTYPE [] > { // > protected HandleRef swigCPtr; > internal $csclassname(IntPtr cPtr, bool futureUse) { swigCPtr = new HandleRef(this, cPtr); } > > internal static HandleRef getCPtr(CppWrapper obj) { > return (obj == null) ? IntPtr.Zero : obj.swigCPtr; > } > } > > // Derived proxy classes use this code > // In my wrappers there is no reason to call back into C++ to do an upcast > // (and SWIG doesn't support multiple inheritance anyway), so I removed that > // code from here. Could I ask you to add in a big DANGER sign in your comments here if you are going to post this onto the internet again as you are relying on behaviour that is not guaranteed in the C++ standard and is liable to subtle, hard to track bugs, particularly so as you have suppressed SWIGWARN_CSHARP_MULTIPLE_INHERITANCE. > %typemap(csbody_derived) SWIGTYPE %{ > //private HandleRef swigCPtr; > > internal $csclassname(IntPtr cPtr, bool cMemoryOwn) : base(cPtr, cMemoryOwn) { > // : base($imclassname.$csclassnameUpcast(cPtr), cMemoryOwn) { > //swigCPtr = new HandleRef(this, cPtr); > } > > //internal static HandleRef getCPtr($csclassname obj) { > // return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr; > //} > %} > > ------------------------------------------------------------------- > >> Please try it out in the next day, just use the latest std_vector.i by >> putting it in whichever version of SWIG you have. Get it from: >> http://swig.svn.sourceforge.net/viewvc/swig/trunk/Lib/csharp/std_vector.i? >> view=log > > OK, I'll try to remember to try it. I can't try it until Monday though. > >> Are you saying that the current enumerator implementation, which as you >> say uses objects, can be improved performance-wise? Should we replace >> storing as 'object' with the real collection type? It'll need a slight >> rewrite though as casting null to primitive types (if collection type is >> primitive) doesn't work. > > Yes, you'll get higher performance using the real collection type, especially if the real collection type is something simple like int. I think it's legal to use default(xyz) instead of null, e.g. default(int) is 0 and default(string) is null. Okay good news, but if default(int) will give 0, it is a valid value for int, which breaks the logic in the Current property (which is expecting null), so a minor rewrite is needed. The idea of overriding Equals and GetHashCode and overloading operator== makes sense as it provides reference equals on the C++ instance level rather than on C# instances and I'm thinking of putting this as a default into SWIG. However, using a single base class implementation of this is incorrect and instead I'd generate the methods into every proxy class. With regard to using the C++ operator==, the advice given in the MSDN links above says: "Consider overriding Equals on a reference type if the semantics of the type are based on the fact that the type represents some value(s)". Surely, if there is a C++ operator== the advice then applies and we should be using value equality. If say we are wrapping std::vector<T> where T is a class (not a pointer to a class), then using reference equals is just plain wrong as we are storing the object by value, not reference/pointer. If we are wrapping std::vector<T*> or std::vector<T&> then implementing reference equality makes sense and we could modify the specializations in std_vector.i to do this. William |
From: William S F. <ws...@fu...> - 2009-04-16 00:02:12
|
David Piepgrass wrote: >>> public override int GetHashCode() { >>> return swigCPtr.ToInt32(); >>> } >> XOR high and low bits as suggested in the Object.GetHashCode docs would >> be better - >> http://msdn.microsoft.com/en-us/library/system.object.gethashcode(VS.80).aspx >> >> (for 64 bit pointers). > > If Microsoft follows its own advice, you should be able to simply call swigCPtr.GetHashCode() and it would hash the high and low words for you. But documentation of HandleRef.GetHashCode appears not to have been written. > > I wouldn't worry about it, because I'll bet there isn't a lot of variation in the high-order 32 bits of a 64-bit pointer. Besides, aren't most people still using 32 bit processes? > There are the odd few bravodos using 64 bit Windows. It is a bit nick-pickety, but we need to cover these corner cases if distributed with SWIG, but sure if you aren't interested in 64 bit then it makes no odds. >> Having a single swigCPtr in the inheritance hierarchy is dangerous, see >> comments below. > > Yeah, it's dangerous in general, I know, but it's safe for me personally because I don't use MI in code wrapped by SWIG. > >>> %typemap(csbase) SWIGTYPE *, SWIGTYPE &, SWIGTYPE [], SWIGTYPE >> (CLASS::*) "" >>> // SWIG gives this absurd warning for derived classes: "Warning for >>> // DerivedClass proxy: Base CppWrapper ignored. Multiple inheritance is >> not >>> // supported in C#." Workaround: suppress that warning universally >>> %warnfilter(SWIGWARN_CSHARP_MULTIPLE_INHERITANCE); >> Didn't we fix this by providing the 'replace' attribute - Bug #1794247? >> If not, please lodge a new bug including a small use case. I've seen you >> post your typemaps a few times which is great, but would prefer up to >> date code if doing so again so as to not mislead future 'googlers'. > > I reviewed the bug at > > http://sourceforge.net/tracker/?func=detail&atid=101645&aid=1794247&group_id=1645 > > and I do not understand what the 'replace' attribute is good for; therefore I do not use it. > See the entry dated 10/13/2006 in the CHANGES file, and the documentation at http://www.swig.org/Doc1.3/Java.html#java_code_typemaps. The following shows how you can use it (taken from Examples/test-suite/inherit_target_language.i), where TargetLanguageBase is any C# class: %typemap(csbase, replace="1") MultipleDerived2 "TargetLanguageBase" struct MBase1a { virtual ~MBase1a() {} virtual void a() {} }; struct MBase2b { virtual ~MBase2b() {} virtual void d() {} }; struct MultipleDerived2 : MBase1a, MBase2b {}; The base class for MultipleDerived2 is set to be TargetLanguageBase. The multiple inheritance warning is suppressed for MultipleDerived2 because the 'replace' flag is set. >>> // Normal wrappers (for defined types) use this code >>> %typemap(csbody, noblock=1) SWIGTYPE >>> { // >>> protected bool swigCMemOwn; >>> protected internal $csclassname(IntPtr cPtr, bool cMemoryOwn) : >> base(cPtr) { >>> if (!(swigCMemOwn = cMemoryOwn)) >>> GC.SuppressFinalize(this); >>> } >> This is a neat performance trick I've not seen before which I thought >> might be useful for the default typemaps. But after some pondering I >> think it is too risky to put into the default SWIG typemaps as it is >> possible that some users customisations will set swigCMemOwn to true >> after the constructor is called. I'd suggest making swigCMemOwn >> readonly to future proof your code with a compilation error... once >> you've done that I think you'll find that you could even get rid of the >> swigCMemOwn flag altogether. > > Interesting idea, eliminating swigCMemOwn. One very minor problem: any shmuck can call GC.ReRegisterForFinalize on the object. Anyway, it might be interesting to make swigCMemOwn readonly and then wait to see if anyone posts a regression bug report. > >> Could I ask you to add in a big DANGER sign in your comments here if >> you are going to post this onto the internet again as you are relying on >> behaviour that is not guaranteed in the C++ standard and is liable to >> subtle, hard to track bugs, particularly so as you have suppressed >> SWIGWARN_CSHARP_MULTIPLE_INHERITANCE. > > Well, I only suppressed the warning because it's spurious. Anyway, here's my new comment: > > // Note: In my wrappers there is no reason to call back into C++ to do an > // upcast (and SWIG doesn't support multiple inheritance anyway), so I > // removed that code from here. *** DANGER ***: this violates the letter > // of the C++ standard, and may fail horribly (with a segfault or > // something) if you use this particular typemap while wrapping classes > // that use virtual inheritance or multiple inheritance. > I'm happy now ;) >> The idea of overriding Equals and GetHashCode and overloading operator== >> makes sense as it provides reference equals on the C++ instance level >> rather than on C# instances and I'm thinking of putting this as a >> default into SWIG. However, using a single base class implementation of >> this is incorrect and instead I'd generate the methods into every proxy >> class. > > I don't think that's necessary. If the base-class value of swigCPtr compares equal in two different proxy objects, surely the two proxies point to the same object? Sure, but SWIG doesn't use this common base class paradigm, which is frowned upon in some circles. It therefore would need to be generated into each class which is at the root of any inheritance hierarchy. > >> With regard to using the C++ operator==, the advice given in the MSDN >> links above says: "Consider overriding Equals on a reference type if the >> semantics of the type are based on the fact that the type represents >> some value(s)". Surely, if there is a C++ operator== the advice then >> applies and we should be using value equality. If say we are wrapping >> std::vector<T> where T is a class (not a pointer to a class), then using >> reference equals is just plain wrong as we are storing the object by >> value, not reference/pointer. If we are wrapping >> std::vector<T*> or std::vector<T&> then implementing reference equality >> makes sense and we could modify the specializations in std_vector.i to >> do this. > > Ahh, hmm. I see your point. As it happens, I have been using SWIG to wrap vectors of VALUES like e.g. vector<Point> (which comes out as a list of System.Drawing.Point on the C# side) and vector<int>. Looking at the matter through that lens, I would like to have the IList<T> interface available in cases like that. > > I strongly agree that SWIG ought to detect equality of two C pointers by default. It's better to provide a reasonable default (equality of C pointers) than the unreasonable default SWIG has now (reference equality of proxy objects). > > Equality of C pointers is good enough for many, if not most cases... but vector<T> where T is a SWIG-wrapped type is not one of those cases :( > Okay, unless a patch appears solving all the problems, this is going on my TODO list. William |
From: William S F. <ws...@fu...> - 2009-04-20 18:54:12
|
David Piepgrass wrote: >> David Piepgrass wrote: >>>>> public override int GetHashCode() { >>>>> return swigCPtr.ToInt32(); >>>>> } >>>> XOR high and low bits as suggested in the Object.GetHashCode docs would >>>> be better - >>>> http://msdn.microsoft.com/en- >> us/library/system.object.gethashcode(VS.80).aspx >>>> (for 64 bit pointers). >>> If Microsoft follows its own advice, you should be able to simply call >> swigCPtr.GetHashCode() and it would hash the high and low words for you. >> But documentation of HandleRef.GetHashCode appears not to have been >> written. >>> I wouldn't worry about it, because I'll bet there isn't a lot of >> variation in the high-order 32 bits of a 64-bit pointer. Besides, aren't >> most people still using 32 bit processes? >> There are the odd few bravodos using 64 bit Windows. It is a bit >> nick-pickety, but we need to cover these corner cases if distributed >> with SWIG, but sure if you aren't interested in 64 bit then it makes no >> odds. > > Whether the OS is 64-bit doesn't really matter--what matters is whether the process is 64-bit. If few people are using a 64-bit OS, then fewer still are using 64-bit processes. Anyway, my other point is still valid: if the high bits rarely vary then they are not an important part of the hash code. > > Put another way: given any two 64-bit addresses, often the high 32 bits are the same. But if the high bits are not the same, then the low bits are almost certainly not the same either. > >>> I reviewed the bug at >>> >> http://sourceforge.net/tracker/?func=detail&atid=101645&aid=1794247&group_ >> id=1645 >>> and I do not understand what the 'replace' attribute is good for; >> therefore I do not use it. >> See the entry dated 10/13/2006 in the CHANGES file, and the >> documentation at >> http://www.swig.org/Doc1.3/Java.html#java_code_typemaps. The following >> shows how you can use it (taken from >> Examples/test-suite/inherit_target_language.i), where TargetLanguageBase >> is any C# class: >> >> %typemap(csbase, replace="1") MultipleDerived2 "TargetLanguageBase" >> struct MBase1a { virtual ~MBase1a() {} virtual void a() {} }; >> struct MBase2b { virtual ~MBase2b() {} virtual void d() {} }; >> struct MultipleDerived2 : MBase1a, MBase2b {}; >> >> The base class for MultipleDerived2 is set to be TargetLanguageBase. The >> multiple inheritance warning is suppressed for MultipleDerived2 because >> the 'replace' flag is set. > > So TargetLanguageBase is basically a user-defined, manually-written wrapper to replace the one that SWIG would have generated but doesn't know how to. Right? Well, this use case is unrelated to the way *I* use the csbase typemap. If I were to use the 'replace' flag, it would totally bork my proxy classes. > > You must understand, I am only using csbase as a way to make my proxy classes more efficient, by sharing common code between them instead of inserting identical methods into every single one. Of course, I only want to give this common base class to classes that have NO base class in C++. > > Put another way: by default, the ultimate base class of all SWIG proxies is System.Object. I am using csbase to change the ultimate base class to something else. Fortunately, SWIG supports this. Unfortunately, it issues a meaningless warning that I have to suppress. Capice? It is clear *what* you are trying to achieve, but I'm afraid I do not see *how* you are getting this warning given what you are trying to achieve. Please give an example. In what way does the 'replace' attribute bork your proxy classes and what exactly do you mean by this? William |