Generating bindings

This is a rough overview of the binding generation process.

  1. Convert.exe converts .spec files into a custom xml file, called signatures.xml.
  2. The generator loads signatures.xml, overrides.xml and gl.tm into a custom in-memory representation.
  3. The generator then applies a number of hard-coded rules. These include stripping the prefixes and suffixes of functions, escaping for tokens that start with digits, generation of safe/unsafe overloads for functions taking pointers and handling of CLS-compliance.
  4. Finally, it generates compilable code for C# or C++.

Several command-line switches can influence the generation process: GL vs ES, namespaces, generated code.

What is the best way for you to proceed depends on (a) the amount of functions you wish to add, and (b) whether these functions are available in the old .spec files or the new xml format.

If you only wish to add a handful of functions, the easiest approach might be to define them by hand at the bottom of the signatures.xml file, which can be found under Source/Bind/Specifications/GL2. The format is relatively simple:

<function name="VertexPointer" extension="Core" category="VERSION_1_1_DEPRECATED" version="1.1" deprecated="3.1">
      <returns type="void" />
      <param name="size" type="Int32" flow="in" />
      <param name="type" type="VertexPointerType" flow="in" />
      <param name="stride" type="SizeI" flow="in" />
      <param name="pointer" type="Void*" flow="in" />
    </function>

In this case, VertexPointerType is an enumeration that must be defined in either signatures.xml or overrides.xml. If this enumeration is not found, the generator will fall back to the "All" enumeration, which is equivalent to the non-typesafe GLenum used in the regular C headers.

If you wish to bind a significant amount of functions, such as a whole new OpenGL version, then your best bet is to execute the Converter utility to generate a new signatures.xml file from the latest spec:

cd Binaries/OpenTK/Debug
wget https://cvs.khronos.org/svn/repos/ogl/trunk/doc/registry/public/oldspecs/gl.spec
Convert.exe -p=gl -v=4.3 -o=../../../Source/Bind/Specifications/GL2 gl.spec
Bind.exe

Now you can recompile OpenTK and take a look at the generated specs - the new functions should be there. If they use enums, these will probably appear as "All". You can use overrides.xml to define type-safe enums and improve the generated API.

gl.tm

File generated by Convert.exe

overrides.xml

Xml file generated by Convert.exe

signatures.xml

The generated XML files follow this schema.

<signatures>
  <add>
    <function name="[function name]" extension="[Core|extension]" profile="[profile name]" category="[category]" version="[1.0|1.1|2.0|...]">
        <returns type="[typename]" />
        <param type="[typename]" name="[parameter name]" />
        <param type="[typename]*" name="[parameter name]" count="[array size]/>
    </function>
    <enum name="[enum name]">
        <token name="[token name]" value="[token value]" />
        <use enum="" token="" />
    </enum>
 </add>
</signatures>
 
<overrides>
    <!-- Todo -->
</overrides>

Notes

Functions:

  • name should not contain a prefix, i.e. BufferData instead of glBufferData.
  • extension must be set to "Core" if this is not an extension method. Otherwise, it must be set to extension name in CamelCase. For example, method MapBufferOES should set extension="Oes".
  • [profile name] can be used to discriminate between different profiles of the same spec (for example "full" and "lite" for ES1.1). This attribute is not used at this point.
  • [category] should be set to the correct function category. This is typically defined for extension methods (e.g. TexImage3DOES belongs to category GL_OES_texture_3D). If the category is unknown, this should be set to the same value as the "version" attribute below.
  • [version] must be set to the correct spec version. OpenGL|ES and OpenCL distribute different header files for each spec version, so this can be set to a constant value (e.g. 1.0 for ES1.0). On the other hand, OpenGL and OpenAL distribute a single file that contains functions from all versions.

The extension attribute is used by the generator to distinguish between core and extension methods (the first use plain DllImports, while the latter are only converted to delegates).

The category and version attributes are used by the generator to match enum parameters. An enum parameter may either define an exact type or may be a generic enum (GLenum). In the last case, category and version are used to find a matching enum. If no match exists, the enum "All" will be used.

Parameter typenames are translated to C# as follows: [typename] -> gl.tm -> csharp.tm. The gl.tm typemap file is shipped by Khronos and matches GL types to C types (this file should not be edited). The csharp.tm typemap file is handwritten and maps C types to C# types (this file may be edited).

Typenames that resolve to csharp strings or string arrays are treated specially by the generator for the purposes of marshalling. For this reason, byte* parameters that contain ASCII strings should be overriden by char* or CharPointer parameters.

Enums:

  • [enum name] should be a valid C# enum name in CamelCase.
  • [token name] should be a valid C# enum token in ALL_CAPS. The generator will translate this to camel case.
  • [enum value] may be a hex or dec number, or a string that refers to a different enum token. The generator will recursively resolve token references and will parse the final values to ensure they are well-formed numbers.