I'm playing around with dynamic linkage again. The reason is: the webserver currently has various translators hard coded into it. I want to make these translators dynamically loaded so people can write a translator for Felix, Python, C, Fdoc, Ocaml, etc etc without having to relink the webserver.
I noticed a nastiness: /// xlat1.flx /////////// println "xlat1 initialising"; var s = "init string"; fun xlat(x:string)=> "XLATED <" + x + "> XLATEDEND " + s; export fun xlat of (string) as "xlat"; ///// dlx.flx ///////////////////// println "Dynamic loader test"; var linst1 = Dynlink::init_lib("xlat1.dylib"); println$ "Library initialised"; var lib1 = Dynlink::get_library linst1; var tf = Dynlink::get_thread_frame linst1; var addr1 = Dynlink::dlsym$ lib1, "xlat"; println$ "Got function address " + str addr1; var fn1 = C_hack::cast[address * string --> string] addr1; println$ fn1 (tf, "Hello World"); /////////////////////////// ~/felix>flx --test=build/release dlx Dynamic loader test xlat1 initialising Library initialised Got function address 879072 XLATED <Hello World> XLATEDEND init string ///////////////////////////// Now, the nastiness is that you write: export fun xlat of (string) as "xlat"; but you actually get: var fn1 = C_hack::cast[address * string --> string] addr1; The initial argument is the thread frame of the library. This is present even if the function doesn't seem to need it. This gets in the way of being able to create "pure C libraries" with Felix. That is something we want to do. Of course such libraries cannot use garbage collection, etc etc, at least unless the GC or thread frame object is explicitly passed. BTW: "export" creates extern "C" functions. There's no way to create C++ functions at the moment. This doesn't matter if you're making a library for "dlopen/dlsym" style usage. But it does if you're just linking it at load time OR you're using a table lookup (for example, this is what Python does). By way of explanation of how dynamic linkage works in Felix: Felix loads a library the usual way, but you technically need an instance handle to be created. This captures the thread frame. The instances are reference counted. When you run out of instances the library is dlclosed. Felix does some garbage collection here, to help release libraries. However .. unloading libraries doesn't work very well: this is a design bug in C and Unix which cannot be corrected. The primary killer is static data, however it isn't just data in initialised or uninitialised CSECT (C static data) that's the problem: TEXT (code) is a problem too: code sections can contain read-only constants .. including functions of course. In order to unload a library you have to be sure there are no references at all into the library address space(s). Felix is very pedantic about NEVER generating static variables (although you can hack it in C when required for signal handling, etc). However a lot of stuff it has no control over happens like string literals. [Lets no even get into the impossibility of managing standard I/O streams properly :] So the bottom line is: in general unless one is 100% certain there are no residual references to a dynamically loaded object .. don't try to unload it :) The gc will try to unload it at program termination IF the gc is run then (which it isn't by default). Hopefully that won't crash anything. -- john skaller skal...@users.sourceforge.net http://felix-lang.org ------------------------------------------------------------------------------ This SF email is sponsosred by: Try Windows Azure free for 90 days Click Here http://p.sf.net/sfu/sfd2d-msazure _______________________________________________ Felix-language mailing list Felix-language@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/felix-language