[linux-audio-dev] [semi-OT] EEL 0.1.0

Kjetil Svalastog Matheussen k.s.matheussen at notam02.no
Sat Jan 15 13:46:22 UTC 2005


Steve Harris:
> Yep, for performance coding I would say SC is the best bet, I've seen a
> live coding performance, and it was very impressive. Almost enough to make
> me want to use emacs. Almost ;)
>
> I was thinking of a live C compiler for prototyping and testing
> purposes.
>


What a coincidence! I'm just working on something like that.
This is what you are looking for:

http://tinyurl.com/5bekn

The url above is pointing to the cvs-entry of the file eval-c.scm in the 
snd sound editor. Eval-c is c-code using s-expressions (which I know you 
hate, allthough I don't know why, perhaps you are crazy...), compiled, 
linked and run on the fly. Place the cursor above an eval-c block in 
emacs, press ctrl+alt+x, and there it flies. (I have also added support 
for classes and a lot more, but those additions hasn't been made public 
yet.)

By the way, this is the way lrdf-support is handled in snd.


Quoting:

"
EVAL-C
------

eval-c takes as arguments lisp- and C-like blocks, generates c-code from 
it, and runs it.

Some reasons to use eval-c:

* Easy integration of c-code from within lisp.
  Mix C and Lisp in the same source without making it look strange. 
  (hopefully)
* Use lisp-macros to generate c-code. (There is a special macro function
  called "define-c-macro" that works with eval-c)
* Generate/compile/link/run c-code on the fly.
* Some people think prefix notation is nice.
* Speed. C is faster than guile.
* Hides guile-semantic to access C-code from guile. Less need to read the 
  guile manual.
* Global functions does not need to be defined at the top-level. (that is 
  a good thing,
  right?)


Examples.
--------

The simplest fibonacci function:

(define-c <int> (fib ((<int> n))
		     (if (< n 2)
			 (return n)
			 (return (+ (fib (- n 1))
				    (fib (- n 2)))))))


The define-c macro will produce the following code:

(eval-c ""
	(public
	 (<int> fib (lambda ((<int> n))
		      (if (< n 2)
			  (return n)
			  (return (+ (fib (- n 1))
				     (fib (- n 2)))))))))


The "public" macro will change the code so that it looks something like 
this:

(eval-c ""
	(<int> fib (lambda ((<int> n))
		     (if (< n 2)
			 (return n)
			 (return (+ (fib (- n 1))
				    (fib (- n 2)))))))
	(<static-SCM> fib_eval_c_helper (lambda ((<SCM> n))
					  (return (MAKE_INTEGER (fib 
(GET_INTEGER n))))))
	(run-now
	 (scm_c_define_gsubr "fib" 1 0 0 fib_eval_c_helper)))


And after running the "lambda", "if" and "run-now" macros, eval-c will 
produce and run the following c-code:

int fib (int n){
  if ((n < 2))
    return (n);
  else
    return ((fib ((n - 1)) + fib ((n - 2))));
}
static SCM fib_eval_c_helper (SCM n){
  return (MAKE_INTEGER (fib (GET_INTEGER (n))));
}
static void run_now_1 (){
  scm_c_define_gsubr ("fib", 1, 0, 0, fib_eval_c_helper);
}


The first function is the fibonacci generator, and the
second function is the guile-wrapper. (GET_INTEGER and
MAKE_INTEGER are just simple C macros.)
"run_now"-functions are run once when the file is loaded.

>From guile you now have a function called "fib" which takes
one argument.



Hello world looks like this:

(eval-c ""
	(run-now
	 (printf (string "Hello world!\\n"))))


First argument to eval-c is a string with compiling/linking options.
Usually just "", but can be "-lsnd" or something if needed.

"

-- 




More information about the Linux-audio-dev mailing list