00001 #region License
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #endregion
00027
00028 using System;
00029 using System.Collections.Generic;
00030 using System.Text;
00031 using System.Reflection;
00032 using System.Runtime.InteropServices;
00033 using System.Diagnostics;
00034
00035 namespace OpenTK
00036 {
00040 public abstract class BindingsBase
00041 {
00042 #region Fields
00043
00047 readonly protected Type DelegatesClass;
00048
00052 readonly protected Type CoreClass;
00053
00057 readonly protected SortedList<string, MethodInfo> CoreFunctionMap = new SortedList<string, MethodInfo>();
00058
00059 bool rebuildExtensionList = true;
00060
00061 #endregion
00062
00063 #region Constructors
00064
00068 public BindingsBase()
00069 {
00070 DelegatesClass = this.GetType().GetNestedType("Delegates", BindingFlags.Static | BindingFlags.NonPublic);
00071 CoreClass = this.GetType().GetNestedType("Core", BindingFlags.Static | BindingFlags.NonPublic);
00072
00073 if (CoreClass != null)
00074 {
00075 MethodInfo[] methods = CoreClass.GetMethods(BindingFlags.Static | BindingFlags.NonPublic);
00076 CoreFunctionMap = new SortedList<string, MethodInfo>(methods.Length);
00077 foreach (MethodInfo m in methods)
00078 {
00079 CoreFunctionMap.Add(m.Name, m);
00080 }
00081 }
00082 }
00083
00084 #endregion
00085
00086 #region Protected Members
00087
00091 protected bool RebuildExtensionList
00092 {
00093 get { return rebuildExtensionList; }
00094 set { rebuildExtensionList = value; }
00095 }
00096
00112 protected abstract IntPtr GetAddress(string funcname);
00113
00120 protected abstract object SyncRoot { get; }
00121
00122 #endregion
00123
00124 #region Internal Members
00125
00126 #region LoadEntryPoints
00127
00128 internal void LoadEntryPoints()
00129 {
00130
00131
00132
00133
00134 int supported = 0;
00135
00136 FieldInfo[] delegates = DelegatesClass.GetFields(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
00137 if (delegates == null)
00138 throw new InvalidOperationException("The specified type does not have any loadable extensions.");
00139
00140 Debug.Write("Loading extensions for " + this.GetType().FullName + "... ");
00141
00142 Stopwatch time = new Stopwatch();
00143 time.Reset();
00144 time.Start();
00145
00146 foreach (FieldInfo f in delegates)
00147 {
00148 Delegate d = LoadDelegate(f.Name, f.FieldType);
00149 if (d != null)
00150 ++supported;
00151
00152 lock (SyncRoot)
00153 {
00154 f.SetValue(null, d);
00155 }
00156 }
00157
00158 rebuildExtensionList = true;
00159
00160 time.Stop();
00161 Debug.Print("{0} extensions loaded in {1} ms.", supported, time.Elapsed.TotalMilliseconds);
00162 time.Reset();
00163 }
00164
00165 #endregion
00166
00167 #region LoadEntryPoint
00168
00169 internal bool LoadEntryPoint(string function)
00170 {
00171 FieldInfo f = DelegatesClass.GetField(function, BindingFlags.Static | BindingFlags.NonPublic);
00172 if (f == null)
00173 return false;
00174
00175 Delegate old = f.GetValue(null) as Delegate;
00176 Delegate @new = LoadDelegate(f.Name, f.FieldType);
00177 lock (SyncRoot)
00178 {
00179 if (old.Target != @new.Target)
00180 {
00181 f.SetValue(null, @new);
00182 }
00183 }
00184 return @new != null;
00185 }
00186
00187 #endregion
00188
00189 #endregion
00190
00191 #region Private Members
00192
00193 #region LoadDelegate
00194
00195
00196 Delegate LoadDelegate(string name, Type signature)
00197 {
00198 MethodInfo m;
00199 return
00200 GetExtensionDelegate(name, signature) ??
00201 (CoreFunctionMap.TryGetValue((name.Substring(2)), out m) ?
00202 Delegate.CreateDelegate(signature, m) : null);
00203 }
00204
00205 #endregion
00206
00207 #region GetExtensionDelegate
00208
00209
00210 internal Delegate GetExtensionDelegate(string name, Type signature)
00211 {
00212 IntPtr address = GetAddress(name);
00213
00214 if (address == IntPtr.Zero ||
00215 address == new IntPtr(1) ||
00216 address == new IntPtr(2))
00217 {
00218 return null;
00219 }
00220 else
00221 {
00222 return Marshal.GetDelegateForFunctionPointer(address, signature);
00223 }
00224 }
00225
00226 #endregion
00227
00228 #endregion
00229 }
00230 }