Thursday, January 15, 2009

Some Photos Taken Yonder

The Biggesee is located near to my home town Attendorn in the Sauerland region, Germany. It's a beautiful spot except for summer, when there are too many tourists. On that beautiful winter day, there was mostly no one around, though. Behold.

Tuesday, January 06, 2009

Ich bin reich!

Neulich erreichte mich eine Lieferung samt Rechnung; ich hatte per Vorkasse bezahlt. Soweit war also alles in Ordnung, aber irgend jemand hat da beim Programmieren geschlampt oder doch zumindest einige einfache Grundregeln (z. B. Nr. 48) nicht beachtet.

Die schulden mir also aus unerfindlichen Gründen 7,11 Billiarden Euro. Hier ist mein Brief an sie:

Sehr geehrte Damen und Herren,

dieser Tage erreichte mich Ihre Sendung zu meinem Auftrag Nr. 1130 vom
12.11. 2008. Der Sendung lag eine Rechnung bei, die eine ernsthafte
Frage offen lässt. Ich habe die Rechnung als PDF-Datei angehängt.

Der offene Restbetrag ist mit EUR -7,11*10^15 ausgewiesen. Da es sich
hierbei um einen negativen Betrag handelt, stehen Sie bei mir in der
Schuld. Ich hege Zweifel daran, dass Sie 7,11 Billiarden Euro auf
einen Schlag aufbringen können; wir können uns gern auf eine
Ratenzahlung einigen. Diese sollte selbstverständlich auf meine bzw.
Ihre Erben übertragen werden.

Es freut mich sehr, dass Ihnen am Wohl meiner selbst und meiner
Familie auf Generationen hinaus so viel liegt. Ich bin gerne bereit,
Ihnen und Ihren Rechtsnachfolgern Spendenquittungen auszustellen -
auch dies eine Verpflichtung, die ich meinen Erben selbstverständlich
testamentarisch auferlegen werde.

Was die Zahlungsmodalitäten angeht, bin ich flexibel - ich akzeptiere
Überweisungen sowie Schecks.

Mit sehr freundlichen und dankbaren Grüßen,
ein gesegnetes neues Jahr,

Michael Haupt

Mal sehen, was kommt...

Friday, January 02, 2009

COLA: Shared Libraries

Over the Christmas holidays, I wanted to do some programming with COLA. (See my earlier tutorial on this marvellous piece of software.) This included implementing an object library in Pepsi, which was then to be used from a Jolt program. While doing the former was as easy as programming and compiling it as a shared library, the latter would not work right away and required some twiddling. As I think it's a nice thing to be able to use Pepsi shared libraries in Jolt code, I want to share my solution.

This Does Not Work

The first thing is, as mentioned above, to implement and compile the shared library. Here's an example of a very simple hello world library, providing an object that can be sent the sayHello message:

{ import: Object }
Hello : Object ()
Hello sayHello [ 'Hello, world!' putln ]
This can be compiled to a shared library using idc -s hellolib.st. Looking at some Jolt code for Cairo bindings, I found that a shared library can be loaded and initialised like this:
(define mylibhandle (dlopen "hellolib"))
((_dlsym mylibhandle "__id__init__"))
The code above is supposed to open the library and then invoke its __id__init__() function, which is required to get all the objects it contains set up and make them visible to the "object namespace". It does not work, though, because __id__init__(), for shared libraries, requires a parameter, namely a pointer to the _libid variable representing the "object world". Failing to pass this parameter will lead to a crash when the shared library is initialised using the above code.

Patching libid

The _libid variable is normally not exported from libid, so an API extension is required that makes this feasible. Extending libid is very simple in this case, and only requires modifications in three places.

1. The API extension must be declared in id.h, located in the object/id subdirectory of the main COLA directory. This header defines struct __libid, which declares the libid interface. It is divided into several "categories", one of which is called environment, and I thought this would be the place to put a function returning the pointer to _libid. In that category, there is an entry

void *unused31;
which I replaced with the declaration of my new accessor function:
struct __libid *(*libid_p)(void);

2. Said function obviously needs to be implemented. This takes place in libid.c (found next to id.h):

struct __libid *_libid_libid_p(void) {
return &_libid;
}
It simply returns the address of the _libid variable (which is, by the way, declared static struct __libid _libid).

3. The pointer to this function in the _libid structure must be initialised. This is done by adding the following code to the _libid_init() function:

_libid.libid_p = _libid_libid_p;
That's all. Of course, everything needs to be recompiled. I decided to play safe and did a complete rebuild (using make spotless ; make in the COLA directory).

This Also Does Not Work

Some convenience functionality for loading and initialising a shared library from within Jolt can look like this:

(define libid-p ((dlsym "_libid_libid_p")))
(define dloi (lambda (libname)
(let ((libhandle (dlopen libname)))
((_dlsym libhandle "__id__init__") libid-p)
libhandle)))
The dloi function accepts a library name, opens and initialises the library, and returns the library handle.

With this available, the following should work:

(dloi "hellolib")
(define Hello (import "Hello")) ; import the Hello object
[Hello sayHello]
However, it does not. Initialisation of the library fails because it contains some references to the st80 library that the Pepsi compiler, idc, links against by default. Instead, idc must link against the Jolt object library located in the function/objects directory.

Linking Against The Jolt Object Library

Happily, it is very easy to link against the correct object library. The only requirement is to pass (via the -I command line switch) the directory where the objects are stored to idc:

idc -IMY_PATH_TO/function/objects/ -s hellolib.st
The shared library generated from this will be linked against the Jolt library, and with this library, the Jolt code for printing a hello world message finally works.