[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

goo interoperability with c



i wanted to let people know about some recent goo developments.  first 
of all, andrew sutherland has completed his master's thesis on a viral 
computing dialect of goo.  i've made his thesis available through 
www.googoogaga.org

secondly, after doing a bunch of multimedia apps in C i'm now starting 
to integrate them back into goo in order to realize the dream of making 
goo a multimedia-capable language.  one big challenge (and age old 
problem) is how best to interface to c code.  i will describe some new 
goo c interfacing mechanisms that i'm readying for release, but first 
let's consider very briefly four c extension facilities available in 
python: swig, ctypes, c-inline, and pyrex.

swig is a language-neutral semi-automatic header parsing mechanism that 
produces separate c files that get compiled and linked into your 
application.  users are allowed tailor the type mapping according to 
their application.  ctypes is a python facility that allows one to 
import dlls, to enumerate their exported symbols, and to manually 
specify their type interfaces with a special python-based c type 
system.  c-inline permits the definition of c code fragments as python 
objects to be executed later.  c snippets are specified as python 
strings.  finally, pyrex allows the intermixing of c and python code 
implicitly requesting c code by defining python variables with c types. 
  in this way, loops can be completely performed in low overhead c if 
all loop related variables are defined with c types.  the following 
presents a pros/cons evaluation of these four facilities:

   name     pros                    cons
   ------------------------------------------------------------------
   swig     semi-automatic          heavyweight
   ctypes   loads dlls              another c type system
   c-inline lighter weight          cumbersome and no python escapes
   pyrex    even lighter weight     whole other python dialect

in summary, either the solutions are too heavyweight or too 
complicated, where the weight is measured in terms of space and speed 
as well as amount of extra glue code and the complication is measured 
in terms of amount extra mechanism and nuisance to use.  pyrex is the 
most similar in spirit in terms of mixing c and python code, but it 
introduces a whole other c type system and makes compilation dependent 
on their the types of variables.

what i think you really want to do is quite simply be able to inline c 
code directly into goo, escaping back into goo when necessary, relying 
on c for its type system instead of having to mirror it in goo.  this 
approach is simpler than pyrex in that the execution proceeds either 
entirely in c or goo and the distinction is syntactically obvious.  
inlining c turns out to be quite straightforward and appropriate for 
goo because goo relies heavily on a C backend (including during dynamic 
evaluation).

we consider the construction of a simple goo layer on top of a 2d 
subset of opengl.  as the first example consider the definition of a 
goo method for a simplified version of initializing the graphics system:

   (dm gl-setup () #{ glutInitWindowSize( 640, 480 ); })

where the #{ ... } form escapes to C executing a series of C statements 
and evaluates to false.

from here let's consider graphics functions themselves.  for example,

   (dm gl-vertex (x|<flo> y|<flo>) #{ glVertex3f($x, $y); })

shows how the $ operator escapes back into goo evaluating the 
subsequent sexpression (ala unquote in a quasiquote expression).  
unfortunately, in this case, the x and y variables contain goo style 
floats and must first be exported (unboxed) to c style as follows:

   (dm gl-vertex (x|<flo> y|<flo>)
     #{ glVertex3f($(c-export x), $(c-export y)); })

where c-export unboxes the float. c-export methods are defined for all 
the basic goo value types (e.g., <log>, <chr>, <int>, <flo> and <str>). 
   furthermore, users can define their own c-export methods.

unfortunately, embedding direct calls to c-export is verbose and thus 
we introduce a shorthand '@s' which is equivalent to $(c-export s).  
now gl-vertex becomes:

   (dm gl-vertex (x|<flo> y|<flo>) #{ glVertex3f(@x, @y); })

in more advanced situations, the $ operator can also be used to assign 
and create pointers to goo variables.

often times users will need to get values back from c in a functional 
style.  for this we introduce the c expression form #x( ... ) which is 
the same as the c statement form except that its value is the value of 
the enclosed c expression and where the x modifier in the #x( ... ) 
specifies the way to interpret the expression as a goo value.  valid 
modifiers are i for <int>, f for <flo>, s for <str>, c for <chr>, b for 
<log>, and l for <loc>.  for example, one can grab an integer C macro 
constant as follows:

   (dv $gl-line-loop #i( GL_LINE_LOOP ))

from here, top level c definitions can be defined at top level with #{ 
}.  for example, a callback can be defined as follows:

   #{ int gl_idle(int x) { $(gl-idle); } }

this can also be used to introduce structure definitions, typedefs,  
includes, etc.

i'm getting ready to release a new version of goo with this facility 
but would appreciate any feedback on it before then.

jonathan