开发者

struct and destructor

I created the type IntPtr<T> to act like a generic pointer that c/c++ have:

public struct IntPtr<T> : IDisposable where T : struct
{
    private static Dictionary<IntPtr, GCHandle> handles = new Dictionary<IntPtr, GCHandle>();

    private IntPtr ptr;

    public IntPtr(ref T value)
    {
        GCHandle gc = GCHandle.Alloc(value, GCHandleType.Pinned);

        ptr = gc.AddrOfPinnedObject();
        handles.Add(ptr, gc);
    }

    public IntPtr(ref T[] value)
    {
        GCHandle gc = GCHandle.Alloc(value, GCHandleType.Pinned);

        ptr = gc.AddrOfPinnedObject();
        handles.Add(ptr, gc);
    }

    public IntPtr(IntPtr value)
    { ptr = value; }

    public IntPtr(IntPtr<T> value)
    { ptr = value.ptr; }

    public void Dispose()
    {
        if (handles.ContainsKey(ptr))
        {
            GCHandle gc = handles[ptr];
            gc.Free();
            handles.Remove(ptr);
            ptr = IntPtr.Zero;
        }
    }

    public T? this[int index]
    {
        get
        {
            if (ptr == IntPtr.Zero) return null;
            if (index < 0) throw new IndexOutOfRangeException();

            if (handles.ContainsKey(ptr))
            {
                GCHandle gc = handles[ptr];

                if (gc.Target is Array) return ((T[])gc.Target)[index];

                return (T)gc.Target;
            }

            return null;

        }
        set
        {
            if (index < 0) throw new IndexOutOfRangeException();
            // not yet implemented
        }
    }

    private T[] getArray()
    {
        if (handles.ContainsKey(ptr)) return (T[])handles[ptr].Target;

        return null;
    }

    public int Count
    {
        get
        {
            if(handles.ContainsKey(ptr))
            {
                GCHandle gc = handles[ptr];
                if (gc.Target is Array) return ((T[])gc.Target).Length;

                return 1;
            }

            return 0;
        }
    }

    public static implicit operator IntPtr(IntPtr<T> value) { return value.ptr; }

    public static implicit operator T(IntPtr<T> value) { return (T)value[0]; }

    public static implicit operator T[](IntPtr<T> value) { return value.getArray(); ; }

    public static implicit operator T?(IntPtr<T> value) { return value[0]; }

}

It's not complete yet but for now it works, the problem is i keep track of GCHandle by storing them in handles now i need to free the GCHandle once it no more needed so i have to declare a destrcutor but c# don't allow struct to have destrcutor or to override 'Finalize' method and if the such variable of type IntPtr<T> goes out of scope the destruction take place but the GCHandle won't be free.

UPDATE

As an example of this class usage, suppose we going to interpo COAUTHIDENTITY and COAUTHINFO from COM, here what it will look like:

[StructLayout(LayoutKind.Sequential)]
struct COAUTHIDENTITY
{
    [MarshalAs(UnmanagedType.LPWStr)] string User;
    uint UserLength;
    [MarshalAs(UnmanagedType.LPWStr)] string Domain;
    uint DomainLength;
    [Mar开发者_Python百科shalAs(UnmanagedType.LPWStr)] string Password;
    uint PasswordLength;
    uint Flags;
}

[StructLayout(LayoutKind.Sequential)]
struct COAUTHINFO
{
    uint dwAuthnSvc;
    uint dwAuthzSvc;
    [MarshalAs(UnmanagedType.LPWStr)] string pwszServerPrincName;
    uint dwAuthnLevel;
    uint dwImpersonationLevel;
    IntPtr<COAUTHIDENTITY> pAuthIdentityData;
    uint dwCapabilities;
}

Instead to make pAuthIdentityData an IntPtr and use Marshal member functions to get object of type COAUTHIDENTITY, IntPtr<T> will make it more simple.

The question is: where should i write the code to free GCHandle when the IntPtr<T> is released?


You're reinventing the wheel. Look at the SafeHandle class. Use an existing descendant or create your own descendant.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜