[HOpenGL] renderString not working in ghci

Sven Panne Sven.Panne at aedion.de
Mon Jun 1 18:39:07 EDT 2009


Am Montag, 1. Juni 2009 22:48:56 schrieb Duncan Coutts:
> I don't know how the problem reported in that message is related to the
> renderString problem (which I do not understand), but the behaviour you
> see there is not terribly surprising. It's an artefact of the way
> dynamic linking works and should not generally cause any problems.

The word "generally" is a problem in itself. ;-) The main point is that GHCi'l 
dynamic linker behaves differently from the system's dynamic linker, so this 
is a very good reason to consider this a bug. It might not surface very often, 
but it is nevertheless a different behaviour a.k.a. bug.

> The only case where it should make a difference is if code is assigning
> any meaning to the address of functions, eg to compare them for
> identity. In that case going via a thunk will make a difference. Is that
> what freeglut is doing do you think?

It is not about the address of functions, it is about data addresses. Here is 
the relevant snippet from GLUT's/freeglut's header file for non-Windows 
platforms:

----------------------------------------------------------------------
    /*
     * I don't really know if it's a good idea... But here it goes:
     */
    extern void* glutStrokeRoman;
    extern void* glutStrokeMonoRoman;
    extern void* glutBitmap9By15;
   ...

    /*
     * Those pointers will be used by following definitions:
     */
#   define  GLUT_STROKE_ROMAN               ((void *) &glutStrokeRoman)
#   define  GLUT_STROKE_MONO_ROMAN          ((void *) &glutStrokeMonoRoman)
#   define  GLUT_BITMAP_9_BY_15             ((void *) &glutBitmap9By15)
...
----------------------------------------------------------------------

As you can see, GLUT's fonts are represented by the addresses of global 
variables. This might not be the nicest way to do this, but it has to be done 
for binary compatibility reasons and there is *nothing* dubious about this. 
Note that e.g. we are very lucky that "errno" is a macro for a function call 
on all platforms for which -fPIC is relevant, otherwise we would have the same 
problem with it, too.

The GLUT Haskell package uses a simple C wrapper around these macros:

----------------------------------------------------------------------
void*
hs_GLUT_marshalBitmapFont(int fontID)
{
  switch (fontID) {
  case 0 : return GLUT_BITMAP_8_BY_13;
  case 1 : return GLUT_BITMAP_9_BY_15;
  case 2 : return GLUT_BITMAP_TIMES_ROMAN_10;
  case 3 : return GLUT_BITMAP_TIMES_ROMAN_24;
  case 4 : return GLUT_BITMAP_HELVETICA_10;
  case 5 : return GLUT_BITMAP_HELVETICA_12;
  case 6 : return GLUT_BITMAP_HELVETICA_18;
  }
  return (void*)0;
}
----------------------------------------------------------------------

For reasons explained in great length in the mail thread quoted, GHCi's linker 
doesn't link the wrapper correctly on some platforms when -fPIC is not used 
for its compilation.

> I rather suspect it's freeglut doing something dubious with comparing
> function pointers.

The only one doing dubious things is GHCi's dynamic linker... ;-)

> On most platforms -fPIC imposes some overhead and so it is only used
> when it's advantageous or necessary. On most platforms code that will
> live in a shared library should or must be compiled with -fPIC. x86-64
> is one of the few architectures where the overhead is relatively low.

So my question is again: Why is -fPIC not the default for GHC on x86_64? If we 
don't want the overhead, that's OK (any benchmark numbers?), but then GHC's 
documentation should really contain a big, fat warning that GHCi's dynamic 
linker gets cases like the one above wrong.

Cheers,
   S.


More information about the HOpenGL mailing list