[gambit-list] moving to blackhole

Per Eckerdal per.eckerdal at gmail.com
Tue Oct 6 04:58:36 EDT 2009


First of all, as previously mentioned, (import "sdl-ttf") is not at  
all the same thing as (import sdl-ttf), and the latter is what you  
want to do.

Also, (load "~~/lib/modules/build") should not be inside of any module  
source code file. BH is designed to be loaded into the development  
environment, but should not be required to be included with  
distributed binaries; having that on the top of files would hinder that.

What is done instead is to fire up a gsc REPL, and then do (load "~~/ 
lib/modules/build") from there. (This is normally done with a script.  
That's what bsc is.)

Another not-so-obvious thing is that you don't compile scheme files  
from the command line like you do with gsc; you use the procedure | 
module-compile!|, for instance (module-compile! 'ttf-sdl)

These are the obvious problems on the surface that I can see. The main  
problem, however, is that BH is designed mainly to be used on its own.

> This what I'm trying to do:
>
> ../src/sdl-interface.scm is a third party library
> sdl-ttf.scm is a library i'm trying to keep independent of blackhole,
> since i want to contribute it to the sdl-interface project
> test-ttf.scm (the unnamed file above) is an attempt to get a minimal
> piece of code that uses both blackhole and sdl-ttf. i ultimately want
> to make an app that uses libraries out of blackhole, and the
> non-blackhole sdl-interface.
>
> Can I compile sdl-interface and sdl-ttf separately and then link them
> with ttf-test via blackhole?

As you might have understood by the other answers on the list, this is  
stretching beyond normal usage of BH. Because it's Gambit however, the  
answer is obviously not a no, the question is how much hackage that is  
required.

If sdl-ttf or sdl-interface exports macros, you're in trouble. That is  
the biggest difficult problem that BH solves, and hacking around that  
is most likely not worth the effort. If it's just a few macros, you  
might get away with re-implementing them in BH, in a module that also  
re-exports sdl-ttf and/or sdl-interface.

You can compile sdl-interface and sdl-ttf separately using the normal  
Gambit workflow, and then use the |load| procedure to load them into  
the Gambit environment. You'd have to make sure yourself that |load|  
is called at the proper time, and only once, but I guess you knew that  
already.

After loading them into the Gambit environment, problem is to make  
sure that BH doesn't protect you away from using the external  
libraries' names.

BH is essentially a big renaming engine. What it does is to make sure  
that name clashes don't occur. One part of that is prefixing all top- 
level names with unique namespaces, for instance "sdl-ttf#". So,  
assuming that ttf-test.scm is assigned the namespace "ttf-test#", all  
references to globals in ttf-test.scm that BH doesn't recognize to be  
from another module will be prefixed with ttf-test#.

So if you just load the external libraries, a call to SDL::Delay will  
be renamed to ttf-test#SDL::Delay.

There are a couple of possible workarounds:

* BH doesn't touch identifiers that contain a #. So if you use  
Gambit's namespace mechanism in the non-BH libraries to add a  
namespace prefix to all their names, you will be able to use it like  
sdl#SDL::Delay.

* Another hack that can be used is that BH doesn't touch what's inside  
##let. So you can get SDL::Delay with (##let () SDL::Delay)

* And the least hacky one: Use a module loader. For this one I added  
some utility functions to BH, so make sure to get the latest version  
from github, and don't forget to recompile build.o1.

Either from the REPL, or in some initialization code that is run after  
BH is loaded, execute something like this:

(module-resolver-add!
  'sdl
  (make-external-module-resolver
   ;; This is the module name. Not really important. Choose something  
descriptive.
   "sdl"
   ;; This is a list of files that BH should load when importing;
   ;; if you want to load the files manually, leave it
   ;; empty. Otherwise add the paths, as strings, here, without
   ;; extensions.
   '()
   ;; This is a list of the identifiers that are imported.
   '(SDL::Delay)
   ;; Next is an optional argument. It's used if the file(s) that are
   ;; being imported have a namespace prefix. It's "" by default, but
   ;; could be something like "sdl#". Theoretically, you could pass
   ;; "SDL::" here, to remove the prefix so that BH modules don't need
   ;; to use it. Later on, you could use BH's functionality for
   ;; prefixing instead, for greater flexibility. For that, you should
   ;; remove the SDL:: prefixes in the previous argument as well.
   ))

Note that, depending on when you do it, you might need to prefix  
module-resolver-add! and make-external-module-resolver with module#.

Nicola Archibald wrote a message on the gambit list not too long ago  
about a neat way of loading BH by modifying /usr/local/Gambit-C/lib/ 
gambcext and letting bsc be a symlink. You might want to look into  
that, since that would provide a natural place for you to insert the  
code above.

You should then be able to do (import (sdl)). Note that this code  
isn't really tested. Tell me if you choose to use it and it doesn't  
work.

/Per


More information about the Gambit-list mailing list