Hey guys, I don't know if anyone would be interested in this, but I've been playing around with the idea of using Scheme underneath Erlang. I'm very new to both Erlang and Scheme, and I was hoping to be able to seamlessly create Scheme nodes within Erlang. Because of Erlang's own implementation of lightweight processes, it turns out that it can't be as seamless as I had hoped, but I created a Gambit Erlang FFI to see what it would be like anyway.
download it here (it only compiles on OS X, but very small tweaks to the makefile could fix that): http://dimlylitblog.com/projects/erlang-ffi.tar.gz
To be able to take advantage of all of Erlang's distributing mechanisms, we need to use a proxy Erlang process and communicate through ports, as described here:
http://www.erlang.org/doc/tutorial/erl_interface.html#5
This is what my FFI is based on. It's a very basic implementation, but it allows to write a Scheme app like this:
(load "erlang")
(define (bar num) (+ num 2))
(define (foo num) (* num 2))
(define (start) (start-erl) (let loop ((term (erl-receive))) (if (not (eqv? term 'close)) (begin (let* ((fun (car term)) (args (cdr term)) (res (apply (eval fun) args))) (erl-send (erl-element res)) (loop (erl-receive)))))))
(start)
And then in Erlang do this:
2> test:start("./test_process"). <0.38.0> 3> test:call({foo,10}). 20 4> test:call({foo,12}). 24 5> test:call({foo,25.2}). 50.4000 6> test:call({foo,12.25}). 24.5000 7> test:call({bar,100}). 102 8> test:call({bar,100.123}). 102.123 9>
Unfortunately, it's still not quite as solid as I would like. It communicates over standard in and out, which just seems hacky to me. However, this is my first FFI and it was a good experience. I have a couple questions after writing this though:
1. One of the biggest problems which made development difficult is that if the Scheme node hit any run-time error I cannot see it from Erlang at all. I could catch the exceptions myself and propagate them properly, however there seems to be run-time errors which are syntactual/macro errors, etc. would there be any good methods to detect and this log those kinds of errors?
2. When I compile the Erlang FFI, gcc gives this warning: erlang.c:2530: warning: target of assignment not really an lvalue; this will be a hard error in the future
and I think it's talking about assigning the result of a c function to ___result, such as
___result = ERL_TUPLE_SIZE(___CAST(ETERM*,___arg1));
any thoughts on that?
3. On OS X, when compiling the FFI into a loadable library, I give gsc options to pass to the linker to link in the erl_interface libraries. It compiles, but when run it gives the error that any of the Erlang c functions can't be found in the flat namespace. I thought that it might be compiling the library with the two level namespace, so I added -flat_namespace to the linker options but it didn't help. I finally figured out that it needed the option "bundle_loader" to work, and I initially tried -bundle_loader $(gsi), but I have no idea why that made it work. I then tried -bundle_loader /bin/ls and even that worked! I understand the purpose of the bundle_loader option, but this should all be in the flat namespace. Has anyone encountered this?
I think those are the only things I didn't really understand :)
James