Commits

Jason McKesson committed b6cd540

Docs for pointer_cpp

  • Participants
  • Parent commits 7c2cc6e

Comments (0)

Files changed (4)

File Style_Creation.wiki

 
 A {{{style}}} is a Lua table that contains a number of functions and tables. These functions will be called by the system to do specific things at specific times.
 
-You should not need to keep state between function invocations (the {{{pointer_c}}} style works completely statelessly, relying only on function arguments). However, you can use local variables to store state if you wish. The system will never ask your style to run twice (at least, not without a process restart).
+You should not need to keep state between function invocations (the {{{pointer_c}}} style works completely statelessly, relying only on function arguments). However, if you need state, you can create it by using the {{{Create}}} function to associate actual state with each instance. The system guarantees that the particular table returned by your style's {{{Create}}} function will only be used to generate a single header/source pair.
 
 The {{{style}}} table will need two sub-tables named {{{source}}} and {{{header}}}. They contain functions for generating material for source and header files, respectively. Most of the functions are in these two sub-tables.
 
 Your style may create global definitions and so forth that come into conflict with other things. Here are the rules you need to follow:
 
 * The user should be able to use different specs with the same style and link them together in the same program without conflicts. Files generated like this should coexist. This effectively means that you need to make sure that your names are prefixed with something spec-specific. The {{{spec}}} table has functions to get an appropriate prefix; the {{{spec.DeclPrefix}}} is the general prefix for declaration/definitions of things that can conflict at link time.
-* The user should be able to #include the standard headers for OpenGL/GLX/WGL //after// your generated header without incident. So you need to #define various values to prevent the inclusion of standard headers (or include them yourself).
-* If the user tries to #include the standard spec headers //before// your generated header, you should provide an appropriate compile-time error. So you need to test to see if standard variables are included, and fail with a {{{#error}}} if they are.
 * The user should be able to supply a prefix with the {{{-prefix}}} option. The user should be able to generate two separate source/header files with the //exact same options// with the exception of the prefixes. That is, the user can supply the same specification, version, extensions list, etc. And both files should be able to be linked together into a single program entirely without incident. Both loaders should be able to co-exist peacefully; loading function pointers for one should not impact the loading of function pointers for another\\Note: if your style does static linking, such as for Linux or OSX, then the part about loading pointers for one not impacting the other can be ignored.\\This rule effectively means that you must prefix every non-static definition. Namespace scoping would also work, if you use the prefix as the namespace (or prefix the namespace with it).\\The prefix string is in {{{options.prefix}}}. Note that it will always be present; if you want to test for a user-defined prefix, test it against the empty string.
 
 So prefix names that can conflict with the user-prefix //and// the spec's prefix.
 
   header.WriteBeginDecl(hFile, spec, options)
 
-    //For each user-specified extension
-    header.WriteExtVariableDecl(hFile, extName, specData, spec, options)
-    header.WriteExtVariableDecl(hFile, ..., specData, spec, options)
-    ...
+    header.WriteBeginExtVarDeclBlock(hFile, spec, options)
+      //For each user-specified extension
+      header.WriteExtVariableDecl(hFile, extName, specData, spec, options)
+      header.WriteExtVariableDecl(hFile, ..., specData, spec, options)
+      ...
+    header.WriteEndExtVarDeclBlock(hFile, spec, options)
 
     header.WriteBeginEnumDeclBlock(hFile, spec, options)
-
       //For each enum to be written, in order of extensions/core
       //Will call one or the other.
       header.WriteEnumDecl(hFile, enum, enumTable, spec, options)
       header.WriteEnumPrevDecl(hFile, enum, enumTable, spec, options, extName)
-
     header.WriteEndEnumDeclBlock(hFile, spec, options)
 
 
     header.WriteBeginFuncDeclBlock(hFile, spec, options)
-    
       //For each user-specified extension:
       header.WriteBeginExtFuncDeclBlock(hFile, extName, spec, options)
-      
         //For each function in that extension
         header.WriteFuncDecl(hFile, func, typemap, spec, options)
         header.WriteFuncDecl(hFile, ..., typemap, spec, options)
         ...
-      
       header.WriteEndExtFuncDeclBlock(hFile, extName, spec, options)
       
       //For each version, where applicable:
         //For each core extension that was not user-specified:
         header.WriteBeginExtFuncDeclBlock(hFile, extName, spec, options)
-          
           header.WriteFuncDecl(hFile, func, typemap, spec, options)
           header.WriteFuncDecl(hFile, ..., typemap, spec, options)
           ...
-          
         header.WriteEndExtFuncDeclBlock(hFile, extName, spec, options)
 
         //For each core function from this version *not* in a core extension.
         header.WriteFuncDecl(hFile, func, typemap, spec, options)
         header.WriteFuncDecl(hFile, ..., typemap, spec, options)
         ...
-
-    header.WriteBeginFuncDeclBlock(hFile, spec, options)
+    header.WriteEndFuncDeclBlock(hFile, spec, options)
     
-    header.WriteUtilityDecls(hFile, spec, options)
-    header.WriteMainLoaderFuncDecl(hFile, spec, options)
-    header.WriteVersioningFuncDecls(hFile, spec, options) //Only if the spec has versions.
+    header.WriteBeginSysDeclBlock(hFile, spec, options)
+      header.WriteUtilityDecls(hFile, spec, options)
+      header.WriteMainLoaderFuncDecl(hFile, spec, options)
+      header.WriteVersioningFuncDecls(hFile, spec, options) //Only if the spec has versions.
+    header.WriteEndSysDeclBlock(hFile, spec, options)
 
   header.WriteEndDecl(hFile, spec, options)
   
 source.WriteIncludes(hFile, spec, options)
 #include "HEADER_FILENAME"
 
+//Function pointer loader func from spec.loaderFunc()
+
 source.WriteBeginDef(hFile, spec, options)
 
-  //For each user-specified extension
-  source.WriteExtVariableDef(hFile, extName, specData, spec, options)
-  source.WriteExtVariableDef(hFile, ..., specData, spec, options)
-  ...
+  source.WriteBeginExtVarDefBlock(hFile, spec, options)
+    //For each user-specified extension
+    source.WriteExtVariableDef(hFile, extName, specData, spec, options)
+    source.WriteExtVariableDef(hFile, ..., specData, spec, options)
+    ...
+  source.WriteEndExtVarDefBlock(hFile, spec, options)
   
   //For each user-specified extension:
   source.WriteBeginExtFuncDefBlock(hFile, extName, spec, options)
       //For each function in the extension
       source.WriteCoreFuncLoader(hFile, func, typemap, spec, options)
     source.WriteEndExtLoaderBlock(hFile, extName, spec, options)
-    
   source.WriteEndExtFuncDefBlock(hFile, extName, spec, options)
   
   source.WriteBeginCoreFuncDefBlock(hFile, version, spec, options)
   source.WriteEndCoreFuncDefBlock(hFile, version, spec, options)
   
 
-  source.WriteUtilityDefs(hFile, specData, spec, options)
-  source.WriteMainLoaderFunc(hFile, specData, spec, options)
-  source.WriteVersioningFuncs(hFile, specData, spec, options) //Only if the spec has versions.
+  source.WriteBeginSysDefBlock(hFile, spec, options)
+    source.WriteUtilityDefs(hFile, specData, spec, options)
+    source.WriteMainLoaderFunc(hFile, specData, spec, options)
+    source.WriteVersioningFuncs(hFile, specData, spec, options) //Only if the spec has versions.
+  source.WriteEndSysDefBlock(hFile, spec, options)
 
 source.WriteEndDef(hFile, spec, options)
 }}}
 
 ==Style function reference==
 
-The reference documentation for style functions is available here.
+The file {{{modules/SampleStyle.lua}}} contains a file that you can simply copy and paste to start making a style. Every function you need to define is listed, as well as comments explaining exactly what they should do. Coupled with this documentation, you should be well on your way to getting a style working.

File Style_Pointer_C.wiki

 
 The loading function that loads the extensions and OpenGL version is called {{{LoadFunction}}}, prefixed by a specification-specific prefix. The return value of this function, as well as the value stored in the extension variables, is special. There is an enumeration, prefixed again by the spec-specific prefix.
 
-If the value is {{{LOAD_FAILED}}}, then the extension was not found in the extension string, so no attempt was made to load it. If the value is {{{LOAD_SUCCEEDED}}}, then the extension was loaded in its entirety (all function pointers accounted for). Otherwise, some number of function pointers failed to load. To get the number of functions that failed to load for the extension, take the integer value and subtract {{{LOAD_SUCCEEDED}}} from it.
+If the value is {{{LOAD_FAILED}}}, then the extension was not found in the extension string, so no attempt was made to load it. If the value is {{{LOAD_SUCCEEDED}}}, then the extension was loaded in its entirety (all function pointers accounted for, if it has some). Otherwise, some number of function pointers failed to load. To get the number of functions that failed to load for the extension, take the integer value and subtract {{{LOAD_SUCCEEDED}}} from it.
 
 The return value for the function loader works mostly the same way. {{{LOAD_FAILED}}} does not signal the failure to load the core functions or some extensions. It signals the failure of the process to work //at all.// This is for something very basic, like the failure to get the function pointers needed to get the extension string. Without the extension string, we cannot detect what should and shouldn't be loaded. Therefore, if this is returned, //nothing// was loaded.
 

File Style_Pointer_CPP.wiki

+The {{{pointer_cpp}}} style is designed to work well in C++. Where {{{pointer_c}}} maximizes interoperability with other systems (it defines global functions with the expected C names), {{{pointer_cpp}}} is primarily about making it easy for intellisense and the like to find the function definitions for easy work.
+
+With the exception of the typedefs, everything lives in a C++ namespace based on each spec: {{{gl}}}, {{{wgl}}}, and {{{glx}}}. If the {{{-prefix}}} option was provided, then the spec namespace will itself be within a namespace named for the prefix.
+
+The extension variables are in their own namespace: {{{<prefix>::<spec>::exts}}}. The type of the variable is not a mere {{{bool}}}; it is an {{{exts::LoadTest}}}. This type is convertible to bool (via the safe-bool idiom, so no need to worry about that), but it also has a function to see how many functions failed to load for that extension. It will always report that it loaded if the extension string is in the spec; the {{{exts::LoadTest::GetNumFailed()}}} will return the number of functions that failed to load (if any).
+
+The enumerators are actual C++ enums now. There is no enumeration name; all of the enums live in one big enumeration. Because the enumerators are namespace-qualified now, there is no need to put the {{{(W)GL(X)_}}} in front of them. So we do not. However, this causes two problems:
+
+# Some enumerators ({{{2D}}}, for example. Yes, that is an OpenGL enumerator; it's for feedback rendering) begin with characters that C++ doesn't allow as identifiers. Thus, these enumerators are prefixed with an "{{{_}}}" character. So {{{2D}}} becomes {{{_2D}}}.
+# Certain enumerators use widely used by OS's for various things. Windows for example {{{#define}}}s {{{TRUE}}} and {{{FALSE}}}, among others. There's no automated way to detect this, so there's just a list of the known ones. These known enumerators will be suffixed with an "{{{_}}}" character. So {{{TRUE}}} becomes {{{TRUE_}}}.
+
+The functions are function pointers, but their names are not hidden behind a {{{#define}}}. This should allow code-completion tools to be more useful. They also aren't prefixed with {{{(w)gl(X)}}}, since they live in a namespace.
+
+The system functions (the function that loads the function pointers, version getting, etc) are contained in the {{{<prefix>::<spec>::sys}}} namespace. The loader function will always be called {{{LoadFunctions}}}. It returns an {{{ext::LoadTest}}}, which works as above. It will only be false if it couldn't even attempt to load functions (due to being unable to get the extension string). The number of functions that failed to load refers to the core functions (and core extension functions).
+
+==Compatibility==
+
+These headers are "compatible" with headers from other libraries (FreeGLUT, GLFW, etc), but only in the sense that they define the appropriate typedefs globally. If any of these headers have inline functions that make calls into GL, expecting functions to be named in the standard GL style, then they're in trouble. Also, these headers //prevent// the later inclusion of {{{gl.h}}} and similar headers, so that kind of code will likely complain.
+
+If you're using some kind of hybrid like this, you need to create an insulation layer between those inline functions and the appropriate typedefs.
 There are a number of styles available, with documentation explaining exactly what they generate:
 
 * {{{[[Style_Pointer_C|pointer_c]]}}}: Used for C-style header generation.
+* {{{[[Style_Pointer_CPP|pointer_cpp]]}}}: Used for creating C++-style loaders, wrapping as much as possible in namespaces.
 
 ==User-created styles==