When Felix makes a top level unit from a file, it synthesises a module name from the file name. For example if you're compiling "mname.flx" the module name will be mname.
In the C++ code generated, everything is put inside namespace flxusr { namespace mname { ... }} This ensures all such units can be linked together without conflict provided the file basenames are distinct (maybe there's even a switch to override this I don't know). Now the problem is that Felix uses dynamic linkage by default, and there are three extern "C" wrapper entry points: "create_thread_frame" ------------------------------- used to construct the thread frame object which contains all the global data. This function just does "new mname::thread_frame_t()" "flx_start" ------------ This runs the procedure "mname::_init_" passing it argv, argc, stdin, stdout, stderr. The three FILE* are passed so that Felix code can do standard I/O without calling any fucked up static objects: that is, to work around the bad design of ISO C and make these files parameters. This also allows redirection. Pointers to the corresponding C++ iostreams are not passed. Actual Felix code can and does still use the non-parametric static objects (should be fixed eventually since re-entrancy is compromised). "flx_main" -------------- You've probably never heard of Felix's replacement for C's main() function. The program driver runs create_thread_frame to make a frame object, then passes it to flx_start, whose job is to initialise it. Most Felix "programs" are just side effects of initialisation. Then, flx_main is called if it exists. This is your actual main program. Whilst "initialisation side effects" are nice for tutorial code, such code can be written in many files and the order in which it runs is indeterminate. To properly setup your environment, you use flx_main and real control flow constructs. As you should always do in C and C++! NEVER use singletons, static initialisers, auto-registration or other crap to do real work: static initialisers are there to initialise strings. Ok, so here's the problem: if you make two such compilation units as plugins you can plug both of them in, no problem! This is because symbols in run time dynamically loaded shared objects do not have to be globally unique: each has its own symbol table which can (and must) be chosen by the handle of the loaded library: SYNOPSIS #include <dlfcn.h> void* dlsym(void* handle, const char* symbol); The problem is that you cannot statically think such units. In particular here's a use case: the Felix webserver. This uses plugins. The webserver itself can be statically linked to the run time -- but it will still use dynamically linked plugins. This can be nice but it makes SHIPPING a binary difficult -- its called DLLHELL :) Ideally, we'd modify the plugin loader so it first searches a registry of preloaded plugins before looking in the file system. Python does this. These preloaded modules are statically linked into the program and somehow registered. But to do this, the first two magic names above have to be replaced by globally unique ones. We don't have to worry about flx_main because no one is using it, and if they did .. well you're only allowed one top level main procedure anyhow. So: it is easy to modify the plugin manager code to use the new naming scheme. The problem is that the flx_run code needs fixed entry points: #ifdef FLX_STATIC_LINK extern "C" void *create_thread_frame; extern "C" void *flx_start; extern "C" void *flx_main; #endif #ifdef FLX_STATIC_LINK flx_dynlink_t library( (thread_frame_creator_t)&create_thread_frame, (start_t)&flx_start, (main_t)&flx_main); #else flx_dynlink_t library; library.link(filename); #endif SO: the only solution I can think of goes like this: (a) generate distinct names (b) take all the startup code and factor it out into a library function: pass the entry points to it (as function pointers). The library function has a fixed name. (c) When "flx" runs, actually generate C++ mainline text if statically linking, which calculates the pointers using the module name (i.e. it emits C++ text with the startup names hard coded in, and does nothing but pass them to the library). That is, generate a thunk. For dynamic linkage we don't need the thunk because we're using dlopen/dlsym anyhow. One advantage of this is that you can make a static archive which contains many programs and just "pick" one to run by generating a thunk (the thunk itself has C main() function). This still leaves open how to register statically linked plugins so the code that currently links to these plugins can search the registry first, before trying dlopen (the actual code has to be transparent, i.e. the webserver should run the same whether one or more plugins happens to be statically linked or not) -- john skaller skal...@users.sourceforge.net http://felix-lang.org ------------------------------------------------------------------------------ LogMeIn Rescue: Anywhere, Anytime Remote support for IT. Free Trial Remotely access PCs and mobile devices and provide instant support Improve your efficiency, and focus on delivering more value-add services Discover what IT Professionals Know. Rescue delivers http://p.sf.net/sfu/logmein_12329d2d _______________________________________________ Felix-language mailing list Felix-language@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/felix-language