// ========================================================== // FreeImage 3 .NET wrapper // Original FreeImage 3 functions and .NET compatible derived functions // // Design and implementation by // - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net) // - Carsten Klein (cklein05@users.sourceforge.net) // // Contributors: // - David Boland (davidboland@vodafone.ie) // // Main reference : MSDN Knowlede Base // // This file is part of FreeImage 3 // // COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY // OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES // THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE // OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED // CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT // THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY // SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL // PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER // THIS DISCLAIMER. // // Use at your own risk! // ========================================================== // ========================================================== // CVS // $Revision: 1.7 $ // $Date: 2009/02/20 07:41:08 $ // $Id: fi_handle.cs,v 1.7 2009/02/20 07:41:08 cklein05 Exp $ // ========================================================== using System; using System.Collections.Generic; using System.Runtime.InteropServices; namespace FreeImageAPI.IO { /// /// Wrapper for a custom handle. /// /// /// The fi_handle of FreeImage in C++ is a simple pointer, but in .NET /// it's not that simple. This wrapper uses fi_handle in two different ways. /// /// We implement a new plugin and FreeImage gives us a handle (pointer) that /// we can simply pass through to the given functions in a 'FreeImageIO' /// structure. /// But when we want to use LoadFromhandle or SaveToHandle we need /// a fi_handle (that we receive again in our own functions). /// This handle is for example a stream (see LoadFromStream / SaveToStream) /// that we want to work with. To know which stream a read/write is meant for /// we could use a hash value that the wrapper itself handles or we can /// go the unmanaged way of using a handle. /// Therefor we use a to receive a unique pointer that we can /// convert back into a .NET object. /// When the fi_handle instance is no longer needed the instance must be disposed /// by the creater manually! It is recommended to use the using statement to /// be sure the instance is always disposed: /// /// /// using (fi_handle handle = new fi_handle(object)) /// { /// callSomeFunctions(handle); /// } /// /// /// What does that mean? /// If we get a fi_handle from unmanaged code we get a pointer to unmanaged /// memory that we do not have to care about, and just pass ist back to FreeImage. /// If we have to create a handle our own we use the standard constructur /// that fills the with an pointer that represents the given object. /// With calling the is used to retrieve the original /// object we passed through the constructor. /// /// This way we can implement a fi_handle that works with managed an unmanaged /// code. /// [Serializable, StructLayout(LayoutKind.Sequential)] public struct fi_handle : IComparable, IComparable, IEquatable, IDisposable { /// /// The handle to wrap. /// public IntPtr handle; /// /// Initializes a new instance wrapping a managed object. /// /// The object to wrap. /// /// is null. public fi_handle(object obj) { if (obj == null) { throw new ArgumentNullException("obj"); } GCHandle gch = GCHandle.Alloc(obj, GCHandleType.Normal); handle = GCHandle.ToIntPtr(gch); } /// /// Tests whether two specified structures are equivalent. /// /// The that is to the left of the equality operator. /// The that is to the right of the equality operator. /// /// true if the two structures are equal; otherwise, false. /// public static bool operator ==(fi_handle left, fi_handle right) { return (left.handle == right.handle); } /// /// Tests whether two specified structures are different. /// /// The that is to the left of the inequality operator. /// The that is to the right of the inequality operator. /// /// true if the two structures are different; otherwise, false. /// public static bool operator !=(fi_handle left, fi_handle right) { return (left.handle != right.handle); } /// /// Gets whether the pointer is a null pointer. /// public bool IsNull { get { return (handle == IntPtr.Zero); } } /// /// Returns the object assigned to the handle in case this instance /// was created by managed code. /// /// assigned to this handle or null on failure. internal object GetObject() { object result = null; if (handle != IntPtr.Zero) { try { result = GCHandle.FromIntPtr(handle).Target; } catch { } } return result; } /// /// Converts the numeric value of the object /// to its equivalent string representation. /// /// The string representation of the value of this instance. public override string ToString() { return handle.ToString(); } /// /// Returns a hash code for this structure. /// /// An integer value that specifies the hash code for this . public override int GetHashCode() { return handle.GetHashCode(); } /// /// Tests whether the specified object is a structure /// and is equivalent to this structure. /// /// The object to test. /// true if is a structure /// equivalent to this structure; otherwise, false. public override bool Equals(object obj) { return ((obj is fi_handle) && (this == ((fi_handle)obj))); } /// /// Indicates whether the current object is equal to another object of the same type. /// /// An object to compare with this object. /// True if the current object is equal to the other parameter; otherwise, false. public bool Equals(fi_handle other) { return (this == other); } /// /// Compares this instance with a specified . /// /// An object to compare with this instance. /// A 32-bit signed integer indicating the lexical relationship between the two comparands. /// is not a . public int CompareTo(object obj) { if (obj == null) { return 1; } if (!(obj is fi_handle)) { throw new ArgumentException("obj"); } return CompareTo((fi_handle)obj); } /// /// Compares this instance with a specified object. /// /// A to compare. /// A signed number indicating the relative values of this instance /// and . public int CompareTo(fi_handle other) { return handle.ToInt64().CompareTo(other.handle.ToInt64()); } /// /// Releases all resources used by the instance. /// public void Dispose() { if (this.handle != IntPtr.Zero) { try { GCHandle.FromIntPtr(handle).Free(); } catch { } finally { this.handle = IntPtr.Zero; } } } } }