2 // The Open Toolkit Library License
4 // Copyright (c) 2006 - 2009 the Open Toolkit library.
6 // Permission is hereby granted, free of charge, to any person obtaining a copy
7 // of this software and associated documentation files (the "Software"), to deal
8 // in the Software without restriction, including without limitation the rights to
9 // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 // the Software, and to permit persons to whom the Software is furnished to do
11 // so, subject to the following conditions:
13 // The above copyright notice and this permission notice shall be included in all
14 // copies or substantial portions of the Software.
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18 // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 // OTHER DEALINGS IN THE SOFTWARE.
28 using System.Runtime.InteropServices;
33 /// Provides a common foundation for all flat API bindings and implements the extension loading interface.
35 public abstract class BindingsBase
38 /// Constructs a new BindingsBase instance.
45 /// Gets or sets a <see cref="System.Boolean"/> that indicates whether the list of supported extensions may have changed.
47 protected bool RebuildExtensionList { get; set; } = true;
50 /// Retrieves an unmanaged function pointer to the specified function.
52 /// <param name="funcname">
53 /// A <see cref="System.String"/> that defines the name of the function.
56 /// A <see cref="IntPtr"/> that contains the address of funcname or IntPtr.Zero,
57 /// if the function is not supported by the drivers.
60 /// Note: some drivers are known to return non-zero values for unsupported functions.
61 /// Typical values include 1 and 2 - inheritors are advised to check for and ignore these
64 protected abstract IntPtr GetAddress(string funcname);
67 /// Gets an object that can be used to synchronize access to the bindings implementation.
69 /// <remarks>This object should be unique across bindings but consistent between bindings
70 /// of the same type. For example, ES10.GL, OpenGL.GL and CL10.CL should all return
71 /// unique objects, but all instances of ES10.GL should return the same object.</remarks>
72 protected abstract object SyncRoot { get; }
75 /// Marshals a pointer to a null-terminated byte array to a new <c>System.String</c>.
76 /// This method supports OpenTK and is not intended to be called by user code.
78 /// <param name="ptr">A pointer to a null-terminated byte array.</param>
80 /// A <c>System.String</c> with the data from <paramref name="ptr"/>.
82 protected static string MarshalPtrToString(IntPtr ptr)
84 if (ptr == IntPtr.Zero)
86 throw new ArgumentException("ptr");
91 sbyte* str = (sbyte*)ptr;
99 return new string((sbyte*)ptr, 0, len, Encoding.UTF8);
104 /// Marshal a <c>System.String</c> to unmanaged memory.
105 /// The resulting string is encoded in UTF8 and must be freed
106 /// with <c>FreeStringPtr</c>.
108 /// <param name="str">The <c>System.String</c> to marshal.</param>
110 /// An unmanaged pointer containing the marshalled string.
111 /// This pointer must be freed with <c>FreeStringPtr</c>
113 protected static IntPtr MarshalStringToPtr(string str)
115 if (String.IsNullOrEmpty(str))
120 // Allocate a buffer big enough to hold the marshalled string.
121 // GetMaxByteCount() appears to allocate space for the final NUL
122 // character, but allocate an extra one just in case (who knows
123 // what old Mono version would do here.)
124 int max_count = Encoding.UTF8.GetMaxByteCount(str.Length) + 1;
125 IntPtr ptr = Marshal.AllocHGlobal(max_count);
126 if (ptr == IntPtr.Zero)
128 throw new OutOfMemoryException();
131 // Pin the managed string and convert it to UTF8 using
132 // the pointer overload of System.Encoding.UTF8.GetBytes().
135 fixed (char* pstr = str)
137 int actual_count = Encoding.UTF8.GetBytes(pstr, str.Length, (byte*)ptr, max_count);
138 Marshal.WriteByte(ptr, actual_count, 0); // Append '\0' at the end of the string
145 /// Frees a marshalled string that allocated by <c>MarshalStringToPtr</c>.
147 /// <param name="ptr">An unmanaged pointer allocated with <c>MarshalStringToPtr</c></param>
148 protected static void FreeStringPtr(IntPtr ptr)
150 Marshal.FreeHGlobal(ptr);
154 /// Marshals a <c>System.String</c> array to unmanaged memory by calling
155 /// Marshal.AllocHGlobal for each element.
157 /// <returns>An unmanaged pointer to an array of null-terminated strings</returns>
158 /// <param name="str_array">The string array to marshal.</param>
159 protected static IntPtr MarshalStringArrayToPtr(string[] str_array)
161 IntPtr ptr = IntPtr.Zero;
162 if (str_array != null && str_array.Length != 0)
164 ptr = Marshal.AllocHGlobal(str_array.Length * IntPtr.Size);
165 if (ptr == IntPtr.Zero)
167 throw new OutOfMemoryException();
173 for (i = 0; i < str_array.Length; i++)
175 IntPtr str = MarshalStringToPtr(str_array[i]);
176 Marshal.WriteIntPtr(ptr, i * IntPtr.Size, str);
179 catch (OutOfMemoryException)
181 for (i = i - 1; i >= 0; --i)
183 Marshal.FreeHGlobal(Marshal.ReadIntPtr(ptr, i * IntPtr.Size));
186 Marshal.FreeHGlobal(ptr);
195 /// Frees a marshalled string that allocated by <c>MarshalStringArrayToPtr</c>.
197 /// <param name="ptr">An unmanaged pointer allocated with <c>MarshalStringArrayToPtr</c></param>
198 /// <param name="length">The length of the string array.</param>
199 protected static void FreeStringArrayPtr(IntPtr ptr, int length)
201 for (int i = 0; i < length; i++)
203 Marshal.FreeHGlobal(Marshal.ReadIntPtr(ptr, i * IntPtr.Size));
205 Marshal.FreeHGlobal(ptr);
208 internal abstract void LoadEntryPoints();