The SoLoad Foreign Function Server (Part I) – An Introduction
The largest obstacle in my path when I try to accomplish anything in scheme is the lack of a standardized foreign function interface (FFI). I understand the reasons for it, I understand that there are many implementations running on platforms and architectures where a foreign function interface wouldn't make any sense, I understand that in some cases, such as JVM-based implementations, any usable FFI would have to look radically different from the standard C library interface that we most often want. I understand all of this, but still it annoys me a little.
My needs in an FFI are simple. All I want to do is to load C libraries such as OpenGL and GTK, and call the functions they export. I don't need anything fancy, like callbacks or continuations. I just want something that lets me make stuff appear on the screen (the ability to use optimized math libraries from within an interpreted language would be a plus, too).
Most implementations offer a C FFI or some sort, but their usage is always radically different. They have different capabilities, and different failure conditions, and even if their mode of operation is the same, the command semantics are usually different. Once you start using one of them, you aren't coding in scheme any more, you're coding in PLT Scheme, or Gambit Scheme, or Chicken Scheme, or any of the myriad other implementations out there. And this is ignoring all those implementations, such as Ikarus, who for the sake of simplicity don't even offer an FFI at all.
There is hope, however. The basic solution looks something like Peter van Eerten's GTK-Server.
Most every scheme implementation makes some provision for starting external programs and talking to them, or at the very least communicating over TCP. Once we realize this, our problem becomes vastly simpler. Our task is no longer to write a standard foreign function interface that unifies all the different schemes out there. All we have to do is come up with an interface that can start an external program, and communicate with it. The semantics for this task are much simpler and often much more similar across implementations than those of an FFI.
Of course, just having this library is no good. If we have that, we're very well placed to use GTK-Server, but essentially no better off at interfacing with any C library that comes along. To make this work, we're going to need something to talk to.
That's what SoLoad is. SoLoad implements a simple text-based protocol which allows you to do some fancy things with C libraries. Using SoLoad, you can open libraries, load functions, and call them, as well as messing around with the types and values of pointers. There is also support for "definition" files, which allow you to load all the defined functionality from a library with a single call.
As well as bringing all of this functionality much closer to portable availability in scheme, the existence of this program has the rather pleasant side effect of making all that functionality availably to any language that has basic process starting and text sending abilities. Feel like programming the next killer FPS in awk, anyone?
Stay tuned for Part 2, in which we learn how to actually make use of SoLoad.
A Minimalistic Module System for Scheme
I like scheme.
I really, really like scheme.
Unfortunately, it seems like a lot of the time the only way to get worthwhile things done in scheme is to abandon the conceptual purity and the elegance, all of the things that make scheme as wonderful as it is.
I figure I'm as good a person as any to try and fix at least a little of that.
The first (second actually, but more about that in the next post) step toward that is some sort of cross-implementation module system. As far as I know, the only such systems in existence so far are SLIB and Snowfort. While both of these are wonderful systems, they overshoot the mark, in my opinion. SLIB aims to be a complete all-singing all-dancing library system, and Snowfort integrates all kinds of package management with the simple act of breaking a program up into modules.
Well, that's the beauty of lisp, isn't it? If you need something, you can just code it yourself.
So I did. The preliminary result is only 19 lines of code, 6 of which are simply a function to build an alist from a key list and a value list. It can also double as a simple object system if you want to use it that way.
Its usage is simple. There are two macros, provide and module. Provide is basically the same as module, but anonymous, so it needs no documentation other than to say that you omit the name.
;;; Show off the usage of simple-module.scm
;;; By Will Donnelly
;; This program is free software. It comes without any warranty, to
;; the extent permitted by applicable law. You can redistribute it
;; and/or modify it under the terms of the Do What The Fuck You Want
;; To Public License, Version 2, as published by Sam Hocevar. See
;; http://sam.zoy.org/wtfpl/COPYING for more details.
(load "simple-module.scm")
;; (module <name> (<exports> ...) <body> ...)
(module mod-name (foo incr)
(define foo 37)
(define i 10) ; i cannot be accessed directly
(define (incr)
(set! i (+ i 1))
i))
(mod-name 'foo) ; => 37
((mod-name 'incr)) ; => 11
((mod-name 'incr)) ; => 12
((mod-name 'incr)) ; => 13
That's all you have to do to use it. The code inside the module system is about as simple as that too.
;;; A minimalistic module system for scheme
;;; By Will Donnelly
;; This program is free software. It comes without any warranty, to
;; the extent permitted by applicable law. You can redistribute it
;; and/or modify it under the terms of the Do What The Fuck You Want
;; To Public License, Version 2, as published by Sam Hocevar. See
;; http://sam.zoy.org/wtfpl/COPYING for more details.
(define (make-alist names values)
(if (equal? (length names) (length values))
(if (> (length names) 0)
(cons (cons (car names) (car values)) (make-alist (cdr names) (cdr values)))
'())
#f))
(define-syntax provide
(syntax-rules ()
((_ (exports ...) body ...)
((lambda ()
body ...
(define export-alist
(make-alist '(exports ...) (list exports ...)))
(lambda (symbol)
(cdr (or (assoc symbol export-alist) '(#f . #f)))))))))
(define-syntax module
(syntax-rules ()
((_ name (exports ...) body ...)
(define name (provide (exports ...) body ...)))))
Just load that code into your scheme interpreter, and you have a simple module system. That's all there is to it.












