Thread: [PyOpenGL-Devel] using ctypes and parsing gl.h & friends.
Brought to you by:
mcfletch
From: Rene D. <re...@py...> - 2004-01-05 14:59:56
|
Hi. I have been thinking about instead of swig using ctypes and some form of automated header parser to make a new pyopengl. As pyopengl needs to be updated to work with a new swig at some point, and all the new opengl functionality needs to be added(up to opengl 1.5); maybe this would be a good time to consider using ctypes for pyopengl. This should result in a much easier to maintain pyopengl, as well as saving disk space, and memory. Below is what I have found out so far. Basically I need some suggestions on a good way to get all the required info from the gl headers. Any feedback would be greatly appreciated. ============================ What is ctypes? If you haven't stumbled accross the wonderful ctypes yet, here is the link: http://starship.python.net/crew/theller/ctypes/ "ctypes is a Python package to create and manipulate C data types in Python, and to call functions in dynamic link libraries/shared dlls. It allows wrapping these libraries in pure Python." =========================== How portable is ctypes? "ctypes now works on Windows, Linux and MacOSX." - ctypes webpage. So I guess that it does not work on a couple of popular platforms. ie *bsd, solaris and irix. However it seems libffi(which is what ctypes uses for non windows platforms) works on most platforms(including ARM, alpha, and ppc). Which means that ctypes should not be too hard to port to most other platforms. As ctypes seems to be becomming more popular hopefully it will reach other platforms soon. ========================================= Reasons for ctypes instead of swig: pyopengl is only at opengl 1.2, we have to catch up to 1.5! There are also lots of extensions to wrap. Unfortunately using swig pyopengl comes in at over 22MB on my linux box, over 7MB on my windows machine. You can get it down to less but you loose debugging info. A lot of this is demo code, and extensions and other stuff. The GL and GLU directories are around 3.2MB on my windows box. The header files I have are (76K, gl.h) , (145K, glext.h), (16K, glu.h). Which should be about the size of data needed to generate the pyopengl functions. Docstrings will be extra. There is also opengl version info needed. Ctypes is around 60-70K on my windows box. Bringing the total to around 350K before docstrings. Not only does a swig generated wrapper use up lots of disk. It also uses up lots of memory. As a lot of code is reproduced amongst the functions. Whereas with ctypes there is not as much duplication, and there is the oportunity to easily add in lazy function generation if wanted. With ctypes the wrappers could be written in python. Probably generating most of the functions at runtime. Making pyopengl coders happy and joyous, instead of frustated and sad. Also means we do not need a c compiler to make pyopengl! ================================ Automating wrapper generation. As more and more functionality is added to OpenGL it becomes insane to hand code the wrappers. It is too much tedious work(which is why pyopengl is at 1.2 and opengl is at 1.5). It is also hard to maintain, and error prone. What are the options for parsing c header files? Preferably something written in python. Even better would be to be part of standard python. - ply - plex - SimpleParse Or maybe something in the standard python distro. eg a bunch of regexen, or maybe a really simple state machine. ===================================== Using ctypes to make the functions. We need a python structure containing: - defines/constants - function names, their arguments, - type definitions(eg GLfloat ->float , GLclampd -> double) - opengl version each part comes from(eg 1.0, 1.1-1.5). - documentation for each part. Hopefully this information can be obtained automatically somehow. I have done some basic tests with ctypes to see how it could be done. Here is a basic demo using ctypes for some bits. This does not show how the pyopengl api would be used, just how ctypes can be used. The pyopengl api should stay very much the same. from OpenGL.GLUT import * from OpenGL.GL import * from OpenGL.GLU import * import ctypes import _ctypes import os, struct # the opengl library you wish to use. Different on different platforms. if os.name == "posix": GL = ctypes.cdll.LoadLibrary("libGL.so") elif os.name == "nt": GL = ctypes.windll.LoadLibrary("opengl32.dll") else: GL = ctypes.cdll.LoadLibrary("libGL.so") # specify a few types here. GLfloat, GLdouble, GLclampd = ctypes.c_float, ctypes.c_double, ctypes.c_double # this loads the function from the library, and makes a python function. GL.glColor3f = GL.glColor3f # we set the types for this function as ctypes # can not figure out the args automatically. GL.glColor3f.argtypes = [GLfloat, GLfloat, GLfloat] import sys, struct def init(): glClearColor(0.0, 0.0, 0.0, 0.0) glShadeModel(GL_SMOOTH) def triangle(): # NOTE: we did not need to specify arguments here for glBegin. GL.glBegin(GL_TRIANGLES) GL.glColor3f(1.0, 0.0, 0.0) glVertex2f(5.0, 5.0) glColor3f(0.0, 1.0, 0.0) glVertex2f(25.0, 5.0) glColor3f(0.0, 0.0, 1.0) glVertex2f(5.0, 25.0) GL.glEnd() def display(): glClear(GL_COLOR_BUFFER_BIT) triangle() glFlush() def reshape(w, h): glViewport(0, 0, w, h) glMatrixMode(GL_PROJECTION) glLoadIdentity() if(w <= h): gluOrtho2D(0.0, 30.0, 0.0, 30.0 * h/w) else: gluOrtho2D(0.0, 30.0 * w/h, 0.0, 30.0) glMatrixMode(GL_MODELVIEW) def keyboard(key, x, y): if key == chr(27): sys.exit(0) glutInit(sys.argv) glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB) glutInitWindowSize(500, 500) glutInitWindowPosition(100, 100) glutCreateWindow('Smooth') init() glutReshapeFunc(reshape) glutKeyboardFunc(keyboard) glutDisplayFunc(display) glutMainLoop() ======================= Platform differences. Extensions need to be loaded on a per platform basis. wgl, glx, etc. Different gl headers. eg different types. Different opengl library names. This will be another nice thing about a ctypes version. You will have more control over which opengl library you load. There are more platform differences, need to get them all listed. ======================================================= Migration from swig pyopengl to ctypes based pyopengl. Will be developed seperately in a different cvs module. Probably PyOpenGL3. To start with it will be base opengl, and nothing else. Seperate parts (eg togl, numeric support) can be added later as seperate modules. Or people can use the ones in PyOpenGL2 in the meantime. If pyopengl with ctypes is not successful there is still swig PyOpenGL2. =================== What about speed? Not sure which is faster swig generated functions or ctype generated ones. Need to test. Probably little difference. Loading speed? May be faster with ctypes version as you do not need to load all the functions at once. Again need to test. Have fun! Rene Dudfield. |
From: Rene D. <re...@py...> - 2004-01-05 13:10:48
|
Hi. I've been thinking about instead of swig using ctypes and some form of automated header parser to make a pyopengl. As pyopengl needs to be updated to work with a new swig at some point, and all the new opengl functionality needs to be added(up to opengl 1.5); maybe this would be a good time to consider using ctypes for pyopengl. This should result in a much easier to maintain pyopengl, as well as saving disk space, and memory. Below is what I have found out so far. Basically I need some suggestions on a good way to get all the required info from the gl headers. Any feedback would be greatly appreciated. ============================ What is ctypes? If you haven't stumbled accross the wonderful ctypes yet, here is the link: http://starship.python.net/crew/theller/ctypes/ "ctypes is a Python package to create and manipulate C data types in Python, and to call functions in dynamic link libraries/shared dlls. It allows wrapping these libraries in pure Python." =================== How portable is ctypes? | "ctypes| now works on Windows, Linux and MacOSX." - ctypes webpage. So I guess that it does not work on a couple of popular platforms. ie *bsd, solaris and irix. However it seems libffi(which is what ctypes uses for non windows platforms) works on most platforms(including ARM, alpha, and ppc). Which means that ctypes should not be too hard to port to most other platforms. As ctypes seems to be becomming more popular hopefully it will reach other platforms soon. ============================ Reasons for ctypes instead of swig: pyopengl is only at opengl 1.2, we have to catch up to 1.5! There are also lots of extensions to wrap. Unfortunately using swig pyopengl comes in at over 22MB on my linux box, over 7MB on my windows machine. You can get it down to less but you loose debugging info. A lot of this is demo code, and extensions and other stuff. The GL and GLU directories are around 3.2MB on my windows box. The header files I have are (76K, gl.h) , (145K, glext.h), (glu.h, 16K). Which should be about the size of data needed to generate the pyopengl functions. Docstrings will be extra. There is also opengl version info needed. Ctypes is around 60-70K on my windows box. Bringing the total to around 350K before docstrings. Not only does a swig generated wrapper use up lots of disk. It also uses up lots of memory. As a lot of code is reproduced amongst the functions. Whereas with ctypes there is not as much duplication, and there is the oportunity to easily add in lazy function generation if wanted. With ctypes the wrappers could be written in python. Probably generating most of the functions at runtime. Making pyopengl coders happy and joyous, instead of frustated and sad. Also means we do not need a c compiler to make pyopengl! =================== Automating wrapper generation. As more and more functionality is added to OpenGL it becomes insane to hand code the wrappers. It is too much tedious work(which is why pyopengl is at 1.2 and opengl is at 1.5). It is also hard to maintain, and error prone. What are the options for parsing c header files? Preferably something written in python. Even better would be to be part of standard python. - ply - plex - SimpleParse Or maybe something in the standard python distro. eg a bunch of regexen, or maybe a really simple state machine. =================== Using ctypes to make the functions. We need a python structure containing: - defines/constants - function names, their arguments, - type definitions(eg GLfloat ->float , GLclampd -> double) - opengl version each part comes from(eg 1.0, 1.1-1.5). - documentation for each part. I have done some basic tests with ctypes to see how it could be done. Here is a basic demo using ctypes for some bits. This does not show how the pyopengl api would be used, just how ctypes can be used. The pyopengl api should stay very much the same. from OpenGL.GLUT import * from OpenGL.GL import * from OpenGL.GLU import * import ctypes import _ctypes import os, struct # the opengl library you wish to use. Different on different platforms. if os.name == "posix": GL = ctypes.cdll.LoadLibrary("libGL.so") elif os.name == "nt": GL = ctypes.windll.LoadLibrary("opengl32.dll") else: GL = ctypes.cdll.LoadLibrary("libGL.so") # specify a few types here. GLfloat, GLdouble, GLclampd = ctypes.c_float, ctypes.c_double, ctypes.c_double # this loads the function from the library, and makes a python function. GL.glColor3f = GL.glColor3f # we set the types for this function as ctypes # can not figure out the args automatically. GL.glColor3f.argtypes = [GLfloat, GLfloat, GLfloat] import sys, struct def init(): glClearColor(0.0, 0.0, 0.0, 0.0) glShadeModel(GL_SMOOTH) def triangle(): # NOTE: we did not need to specify arguments here for glBegin. GL.glBegin(GL_TRIANGLES) GL.glColor3f(1.0, 0.0, 0.0) glVertex2f(5.0, 5.0) glColor3f(0.0, 1.0, 0.0) glVertex2f(25.0, 5.0) glColor3f(0.0, 0.0, 1.0) glVertex2f(5.0, 25.0) GL.glEnd() def display(): glClear(GL_COLOR_BUFFER_BIT) triangle() glFlush() def reshape(w, h): glViewport(0, 0, w, h) glMatrixMode(GL_PROJECTION) glLoadIdentity() if(w <= h): gluOrtho2D(0.0, 30.0, 0.0, 30.0 * h/w) else: gluOrtho2D(0.0, 30.0 * w/h, 0.0, 30.0) glMatrixMode(GL_MODELVIEW) def keyboard(key, x, y): if key == chr(27): sys.exit(0) glutInit(sys.argv) glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB) glutInitWindowSize(500, 500) glutInitWindowPosition(100, 100) glutCreateWindow('Smooth') init() glutReshapeFunc(reshape) glutKeyboardFunc(keyboard) glutDisplayFunc(display) glutMainLoop() =================== Platform differences. Extensions need to be loaded on a per platform basis. wgl, glx, etc. Different gl headers. eg different types. Different opengl library names. This will be another nice thing about a ctypes version. You will have more control over which opengl library you load. There are more platform differences, need to get them all listed. ============================================ Migration from swig pyopengl to ctypes based pyopengl. Will be developed seperately in a different cvs module. Probably PyOpenGL3. To start with it will be base opengl, and nothing else. Seperate parts (eg togl, numeric support) can be added later as seperate modules. Or people can use the ones in PyOpenGL2 in the meantime. If pyopengl with ctypes is not successful there is still swig PyOpenGL2. =================== What about speed? Not sure which is faster swig generated functions or ctype generated ones. Need to test. Probably little difference. Loading speed? May be faster with ctypes version as you do not need to load all the functions at once. Again need to test. Have fun! |
From: Rene D. <re...@py...> - 2004-01-05 18:23:35
|
I've done the functions to generate the opengl functions given a list of ["return_type", "function_name", [arg (type,name),...]] Where the types can be eg GLfloat, GLfloat*, GLfloat**. One thing I forgot to note before was that some functions will need to have utility functions to make them the style they are now. For example: #GLAPI void GLAPIENTRY glGetBooleanv( GLenum pname, GLboolean *params ); GL.glGetBooleanv= GL.glGetBooleanv GL.glGetBooleanv.argtypes = [GLenum, ctypes.POINTER(GLboolean)] print "GL_BLEND is false", glGetBooleanv(GL_BLEND) == GL_FALSE a = GLboolean() GL.glGetBooleanv(GL_BLEND, ctypes.byref(a)) print "GL_BLEND is false", a.value == GL_FALSE ie they are called like this: glGetBooleanv(x) -> y glGetBooleanv(x, *y) To automatically convert these types of functions to the first style might be difficult. As the number of elements in y depends on the value of x. Other functions which have pointers have different calling contracts. There are lots of these types of situations handled in the swig type maps at the moment. Perhaps it may be a good idea to have an api which is as close to the c one as possible. Then build these helper type functionality on top of it. That would probably be more flexible. Another thing pyopengl2 does is check the gl error code after each gl call. This could be built into the layer on top of the base opengl api. Next up is a quick hack set of regexen to 'parse' my gl.h/glext.h headers to make a full list of function prototypes, and constants. Then most of the opengl 1.5 api available! woohoo :) Have fun! Rene Dudfield. |
From: Rene D. <re...@py...> - 2004-01-06 07:36:09
|
Hello, Made a simple 'parser' using a few regex. Which extracts the constants, and function prototypes from my gl.h A more generic parser would be lots better of course, however this was just to test the concept, and it probably will not work with most gl.h files. However with a little bit of modification it could work. I'm going to take a break from this for a few days, and if I hear nothing about a better way to parse .h files I will start work on improving this one. Here are the timings for the loading up things. parsing and making all functions: 0.339720964432 making functions: 0.0477319955826 making one function: 0.000452995300293 storing the parsed available functions in a module, then making all functions: 0.101287007332 storing the parsed available functions in a module, then making one function: 0.0743420124054 PyOpenGL2 loading one function: 0.107846021652 PyOpenGL2 loading everything: 0.110869050026 As you can see parsing the header takes a while, however as you can see if the parsed data is stored making the functions becomes about as fast as pyopengl2. However you have the option of only loading up those functions you need, which can save you a little time(and memory). Of course this doesn't mean much to most people, as 0.11 is fast enough for most. However if you scale it up for all the extensions(or on a slower machine), then this can make a large difference. Anyway... It seems fast enough for loading. Memory is usage is a little less with the ctypes version(almost a megabyte, without parser). This data from top. VIRT RES SHR pyopengl ctypes - 7564 7564 2348 pyopengl ctypes, one function - 7424 7424 2344 pyopengl ctypes, with parser -8232 8232 2416 pyopengl swig - 8856 8856 3372 pyopengl swig, one function - 8832 8832 3372 Loading time, and memory usage will go up once python wrapper functions are added. Have fun! Rene Dudfield. |
From: Rene D. <re...@py...> - 2004-01-11 13:41:12
|
Hey Shane, CCed this to the list as well. > > > Rene, > Looked over the code briefly, and I'd like to say good first pass! > So I've got a couple of questions for you: > > > - Do you want to generate the ctype mapping from the header files on > the first import every run of python? > Would be cached for sure. > - Is it acceptable to cache the generated mapping like Mark Hammonds > win32 extensions for COM imports? > > I'm for the caching, mainly because not everyone has a C compiler > configured, and thereby would not have the GL header files. > However, I think those files could be distributed with the project. > Yep, sure. Just like the interface files are distributed with pyopengl at the moment, the cached mappings would be distributed. > - Does the whole process need to be pure python? Or can we use tools > such as the preprocessor from GCC? > > This definatley adds licensing complexities, but gets the project > farther faster. My thoughts are that we can start with the tools, > and then cull them out as we get them rewritten in pure python. > It would be nice to be pure python, then more people could easily add new functions. However the function generator parts can be done without the parsing bit. So as you say, using other tools to generate the mappings could be useful. Here is a few things TODO(quite a lot of work): - Figure out how best to get extension loading working on different platforms. - try parsing and wrapping GLUT, and GLU, glx, wgl. - I think ctypes may need to be messed with to get callbacks with non-int return values working on non-windows. - Figure out how to automatically get doc strings for everything(or lots of things). - Look for a way to identify api version information. - there are #ifdefs in some header files for this. A regex should be able to extract it. - Find good sources for the api definition. - Different header files, opengl.org, opengl spec, extension registry, delphi3d.net, mesa3d.org - Be really nice if this was in a database allready :) - Seperate subset of the api for OpenGL ES. - setup cvs module, probably PyOpenGL3 A lot of this has allready been done with PyOpenGL2, so that will be a good source of info. Swig and PyOpenGL2 could be used to compare the implementations(eg compare function names/args, docstrings). I'll put the test code I did earlier in the cvs as PyOpenGL3, so people can play around with it. Since there have been no objections or comments about this, I assume no one objects? Have fun! Rene Dudfield. |
From: Rene D. <re...@py...> - 2004-01-14 09:01:45
|
Hey, Thought I'd leave the code out of cvs at the moment, until the code directory structure is in place. If anyone wants to play around with the code so far take a peek at: http://www.py3d.org/files/pyopengl_ctypes.tar.gz GL_base.py - this will contain the base opengl functions, constants, types etc. Has most of opengl 1.4 in there at the moment. Not including extensions. GL_compat.py - will contain current pyopengl api. eg glGetFloatv(pname) -> params instead of glGetFloatv(pname, params). Only has a couple of test functions in there at the moment. From the list of function prototypes we should be able to do something similar to the type matching used in swig to emulate the api easily. Got stupid_parse.py to work with an old mesa3d gl.h header, and old, and new nvidia headers. GL_func_prototypes.py is the output from the stupid_parse.py. It contains a big list of the function prototypes. There will also be a GL_numeric.py at some stage to mix in for those that want to use numeric. The code to mix numeric and ctypes is pretty simple, so it shouldn't take long. This will be enabled in the default api (if use_numeric in the config is set). Another addition which will be kept seperate is automatically calling and handling glGetError(). This will be kept seperate so that people have the option of inflicting long silly debugging sessions on themselves ;) Will be enabled in the default api. There is a simple test program sin_cos_reloaded.py. I see the default api sticking exactly as PyOpenGL2 if possible. However this new system will be able to be used very much like the c opengl api. Which means mixing it with other c/c++ code should be lots easier. Unfortunately I have to do contract work for the next week or so, so will have to continue later. But I'm itching to replace opengl in my game to use some of those new features on my video card :) Have fun! |
From: Mike C. F. <mcf...@ro...> - 2004-01-14 09:13:39
|
Rene Dudfield wrote: > Thought I'd leave the code out of cvs at the moment, until the code > directory structure is in place. Not strictly necessary from my standpoint if you're working in a separate project, but up to you. > If anyone wants to play around with the code so far take a peek at: > http://www.py3d.org/files/pyopengl_ctypes.tar.gz Would love to have time to play with it. I'm particularly curious about the performance of the approach, but alas, other projects are calling for my spare time for the next few weeks. Are you planning to write C accelerator functions for array/list conversions, or do you do all that in Python? Also curious to poke into how you're handling error conditions (since I think we need to make that handling more robust than the current code-base). > There will also be a GL_numeric.py at some stage to mix in for those > that want to use numeric. The code to mix numeric and ctypes is > pretty simple, so it shouldn't take long. This will be enabled in the > default api (if use_numeric in the config is set). Doesn't *everyone* want to use Numeric? I can't even imagine writing a PyOpenGL app without it these days :) . > I see the default api sticking exactly as PyOpenGL2 if possible. > However this new system will be able to be used very much like the c > opengl api. Which means mixing it with other c/c++ code should be > lots easier. Cool. > Unfortunately I have to do contract work for the next week or so, so > will have to continue later. But I'm itching to replace opengl in my > game to use some of those new features on my video card :) Always good to have motivation. Enjoy, Mike _______________________________________ Mike C. Fletcher Designer, VR Plumber, Coder http://members.rogers.com/mcfletch/ |
From: Rene D. <re...@py...> - 2004-01-15 02:45:33
|
Mike C. Fletcher wrote: > Rene Dudfield wrote: > >> Thought I'd leave the code out of cvs at the moment, until the code >> directory structure is in place. > > > Not strictly necessary from my standpoint if you're working in a > separate project, but up to you. > >> If anyone wants to play around with the code so far take a peek at: >> http://www.py3d.org/files/pyopengl_ctypes.tar.gz > > > Would love to have time to play with it. I'm particularly curious > about the performance of the approach, but alas, other projects are > calling for my spare time for the next few weeks. Are you planning to > write C accelerator functions for array/list conversions, or do you do > all that in Python? Also curious to poke into how you're handling > error conditions (since I think we need to make that handling more > robust than the current code-base). > Just doing the list conversion in python with ctypes for the moment. Hopefully there is an existing method fast enough for the conversion. Avoiding c would be nice :) Using the right data structures is important for performance. Unfortunately using python lists with floats is probably out, as they are doubles internally. Meaning there is either twice as much data to transfer, or you have to do memory allocations and conversions. Strings are probably also a bad idea, as they are mutable. Meaning if you pass them through a function or method they are copied. So using one of the array types(Numeric, the array module, or ctypes arrays) is better for performance. Or passing in a pointer(which you can do with ctypes). Having some optional support for detecting these slow uses would be good. Haven't really done any error condition handling yet. For array using functions, probably something like: if numeric array: do it the numeric way elif array: do it array way else: try to do it sequence way, if that fails raise exception Keeping them seperate, ie calling GL_numeric.glVertexPointer would be more explicit on what is happening though. Checking if the past in array is floats when opengl asks for floats is probably a nice thing to do in the compat api. Whatever is done for error checking, it should be much easier to get right with python rather than c :) >> There will also be a GL_numeric.py at some stage to mix in for those >> that want to use numeric. The code to mix numeric and ctypes is >> pretty simple, so it shouldn't take long. This will be enabled in >> the default api (if use_numeric in the config is set). > > > Doesn't *everyone* want to use Numeric? I can't even imagine writing > a PyOpenGL app without it these days :) . > Yeah Numeric is lovely. Allthough I've talked to a few people who don't use it. Eg they allready have a library/3d engine for all their data processing. Cheers :) |
From: Mike C. F. <mcf...@ro...> - 2004-01-19 06:30:27
|
Rene Dudfield wrote: ... > Made a simple 'parser' using a few regex. Which extracts the > constants, and function prototypes from my gl.h > > A more generic parser would be lots better of course, however this was > just to test the concept, and it probably will not work with most gl.h > files. However with a little bit of modification it could work. I've been playing about with the swig 1.3.20 xml generator, seems as though it can produce a fairly decent XML description from the Mesa headers. For example, here's a function from the gl.h header file: <cdecl id="11299" addr="7f1c60" > <attributelist id="11300" addr="7f1c60" > <attribute name="sym_name" value="glCopyTexImage2D" id="11301" addr="836070" /> <attribute name="name" value="glCopyTexImage2D" id="11302" addr="836070" /> <attribute name="decl" value="f(GLenum,GLint,GLenum,GLint,GLint,GLsizei,GLsizei,GLint)." id="11303" addr="836070" /> <parmlist id="11304" addr="7f1820" > <parm id="11305"> <attributelist id="11306" addr="7f1820" > <attribute name="name" value="target" id="11307" addr="836070" /> <attribute name="type" value="GLenum" id="11308" addr="836070" /> </attributelist > </parm > <parm id="11309"> <attributelist id="11310" addr="7f18b0" > <attribute name="name" value="level" id="11311" addr="836070" /> <attribute name="type" value="GLint" id="11312" addr="836070" /> </attributelist > </parm > <parm id="11313"> <attributelist id="11314" addr="7f1940" > <attribute name="name" value="internalformat" id="11315" addr="836070" /> <attribute name="type" value="GLenum" id="11316" addr="836070" /> </attributelist > </parm > <parm id="11317"> <attributelist id="11318" addr="7f19d0" > <attribute name="name" value="x" id="11319" addr="836070" /> <attribute name="type" value="GLint" id="11320" addr="836070" /> </attributelist > </parm > <parm id="11321"> <attributelist id="11322" addr="7f1a60" > <attribute name="name" value="y" id="11323" addr="836070" /> <attribute name="type" value="GLint" id="11324" addr="836070" /> </attributelist > </parm > <parm id="11325"> <attributelist id="11326" addr="7f1af0" > <attribute name="name" value="width" id="11327" addr="836070" /> <attribute name="type" value="GLsizei" id="11328" addr="836070" /> </attributelist > </parm > <parm id="11329"> <attributelist id="11330" addr="7f1b80" > <attribute name="name" value="height" id="11331" addr="836070" /> <attribute name="type" value="GLsizei" id="11332" addr="836070" /> </attributelist > </parm > <parm id="11333"> <attributelist id="11334" addr="7f1c10" > <attribute name="name" value="border" id="11335" addr="836070" /> <attribute name="type" value="GLint" id="11336" addr="836070" /> </attributelist > </parm > </parmlist > <attribute name="storage" value="extern" id="11337" addr="836070" /> <attribute name="type" value="void" id="11338" addr="836070" /> <attribute name="sym_symtab" value="4e0198" id="11339" addr="4e0198" /> <attribute name="sym_overname" value="__SWIG_0" id="11340" addr="836070" /> </attributelist > </cdecl > whereas here's one from the glext.h header: <cdecl id="36477" addr="c96660" > <attributelist id="36478" addr="c96660" > <attribute name="sym_name" value="glPixelTransformParameteriEXT" id="36479" addr="d3a940" /> <attribute name="name" value="glPixelTransformParameteriEXT" id="36480" addr="d3a940" /> <attribute name="decl" value="f(GLenum,GLenum,GLint)." id="36481" addr="d3a940" /> <parmlist id="36482" addr="c96580" > <parm id="36483"> <attributelist id="36484" addr="c96580" > <attribute name="type" value="GLenum" id="36485" addr="d3a940" /> </attributelist > </parm > <parm id="36486"> <attributelist id="36487" addr="c965d0" > <attribute name="type" value="GLenum" id="36488" addr="d3a940" /> </attributelist > </parm > <parm id="36489"> <attributelist id="36490" addr="c96620" > <attribute name="type" value="GLint" id="36491" addr="d3a940" /> </attributelist > </parm > </parmlist > <attribute name="storage" value="extern" id="36492" addr="d3a940" /> <attribute name="type" value="void" id="36493" addr="d3a940" /> <attribute name="sym_symtab" value="4e0198" id="36494" addr="4e0198" /> <attribute name="sym_overname" value="__SWIG_0" id="36495" addr="d3a940" /> </attributelist > </cdecl > the mesa headers don't define argument names for the arguments in the naturally-named function definitions. They do for the PFNGLPIXELTRANSFORMPARAMETERIEXTPROC definitions, however, so that's readily worked around. Not sure if there's a real advantage here, it just seems like it would be a fairly robust mechanism for producing the ctypes function wrappers. Writing a script to process the XML into a reasonable format would seem fairly doable. Doesn't work for the mesa_wgl.h file, btw, but that's a pretty small and static library. Also won't run on the MS Win32 GL.h headers, but oh well, Mesa's headers would seem fine for this kind of task. At the least, this should get the ctypes wrappers up to the same level as a straight run of swig over the headers would provide. Enjoy, Mike _______________________________________ Mike C. Fletcher Designer, VR Plumber, Coder http://members.rogers.com/mcfletch/ |
From: Rene D. <re...@py...> - 2004-01-20 06:07:17
|
Mike C. Fletcher wrote: > Rene Dudfield wrote: > ... > >> Made a simple 'parser' using a few regex. Which extracts the >> constants, and function prototypes from my gl.h >> >> A more generic parser would be lots better of course, however this >> was just to test the concept, and it probably will not work with most >> gl.h files. However with a little bit of modification it could work. > > > I've been playing about with the swig 1.3.20 xml generator, seems as > though it can produce a fairly decent XML description from the Mesa > headers. For example, here's a function from the gl.h header file: > > <cdecl id="11299" addr="7f1c60" > > <attributelist id="11300" addr="7f1c60" > > <attribute name="sym_name" value="glCopyTexImage2D" > id="11301" addr="836070" /> > <attribute name="name" value="glCopyTexImage2D" > id="11302" addr="836070" /> > <attribute name="decl" > value="f(GLenum,GLint,GLenum,GLint,GLint,GLsizei,GLsizei,GLint)." > id="11303" addr="836070" /> > <parmlist id="11304" addr="7f1820" > > <parm id="11305"> > <attributelist id="11306" addr="7f1820" > > <attribute name="name" value="target" > id="11307" addr="836070" /> > <attribute name="type" value="GLenum" > id="11308" addr="836070" /> > </attributelist > > </parm > > <parm id="11309"> > <attributelist id="11310" addr="7f18b0" > > <attribute name="name" value="level" > id="11311" addr="836070" /> > <attribute name="type" value="GLint" > id="11312" addr="836070" /> > </attributelist > > </parm > > <parm id="11313"> > <attributelist id="11314" addr="7f1940" > > <attribute name="name" > value="internalformat" id="11315" addr="836070" /> > <attribute name="type" value="GLenum" > id="11316" addr="836070" /> > </attributelist > > </parm > > <parm id="11317"> > <attributelist id="11318" addr="7f19d0" > > <attribute name="name" value="x" id="11319" > addr="836070" /> > <attribute name="type" value="GLint" > id="11320" addr="836070" /> > </attributelist > > </parm > > <parm id="11321"> > <attributelist id="11322" addr="7f1a60" > > <attribute name="name" value="y" id="11323" > addr="836070" /> > <attribute name="type" value="GLint" > id="11324" addr="836070" /> > </attributelist > > </parm > > <parm id="11325"> > <attributelist id="11326" addr="7f1af0" > > <attribute name="name" value="width" > id="11327" addr="836070" /> > <attribute name="type" value="GLsizei" > id="11328" addr="836070" /> > </attributelist > > </parm > > <parm id="11329"> > <attributelist id="11330" addr="7f1b80" > > <attribute name="name" value="height" > id="11331" addr="836070" /> > <attribute name="type" value="GLsizei" > id="11332" addr="836070" /> > </attributelist > > </parm > > <parm id="11333"> > <attributelist id="11334" addr="7f1c10" > > <attribute name="name" value="border" > id="11335" addr="836070" /> > <attribute name="type" value="GLint" > id="11336" addr="836070" /> > </attributelist > > </parm > > </parmlist > > <attribute name="storage" value="extern" id="11337" > addr="836070" /> > <attribute name="type" value="void" id="11338" > addr="836070" /> > <attribute name="sym_symtab" value="4e0198" id="11339" > addr="4e0198" /> > <attribute name="sym_overname" value="__SWIG_0" > id="11340" addr="836070" /> > </attributelist > > </cdecl > > > whereas here's one from the glext.h header: > > <cdecl id="36477" addr="c96660" > > <attributelist id="36478" addr="c96660" > > <attribute name="sym_name" > value="glPixelTransformParameteriEXT" id="36479" addr="d3a940" /> > <attribute name="name" > value="glPixelTransformParameteriEXT" id="36480" addr="d3a940" /> > <attribute name="decl" value="f(GLenum,GLenum,GLint)." > id="36481" addr="d3a940" /> > <parmlist id="36482" addr="c96580" > > <parm id="36483"> > <attributelist id="36484" addr="c96580" > > <attribute name="type" value="GLenum" > id="36485" addr="d3a940" /> > </attributelist > > </parm > > <parm id="36486"> > <attributelist id="36487" addr="c965d0" > > <attribute name="type" value="GLenum" > id="36488" addr="d3a940" /> > </attributelist > > </parm > > <parm id="36489"> > <attributelist id="36490" addr="c96620" > > <attribute name="type" value="GLint" > id="36491" addr="d3a940" /> > </attributelist > > </parm > > </parmlist > > <attribute name="storage" value="extern" id="36492" > addr="d3a940" /> > <attribute name="type" value="void" id="36493" > addr="d3a940" /> > <attribute name="sym_symtab" value="4e0198" id="36494" > addr="4e0198" /> > <attribute name="sym_overname" value="__SWIG_0" > id="36495" addr="d3a940" /> > </attributelist > > </cdecl > > > the mesa headers don't define argument names for the arguments in the > naturally-named function definitions. They do for the > PFNGLPIXELTRANSFORMPARAMETERIEXTPROC definitions, however, so that's > readily worked around. Not sure if there's a real advantage here, it > just seems like it would be a fairly robust mechanism for producing > the ctypes function wrappers. > > Writing a script to process the XML into a reasonable format would > seem fairly doable. Doesn't work for the mesa_wgl.h file, btw, but > that's a pretty small and static library. Also won't run on the MS > Win32 GL.h headers, but oh well, Mesa's headers would seem fine for > this kind of task. At the least, this should get the ctypes wrappers > up to the same level as a straight run of swig over the headers would > provide. > > Enjoy, > Mike Awesome. That should be quite useful. |