I've had great success with a fourth way: my project language compiles to C, which is loaded at runtime with libtcc (specifically: git://repo.or.cz/tinycc). I've gone down the .so/.dll route a few times in the past, but I can safely say: never again. libtcc has the advantages of a jit (native C speed), but with an elegant API and laudable portability.