
| Going the final step and allowing linkage to the current | binary is possible, it just means the linker has to know how | to read the symbol table out of the binary, and you have to | avoid running 'strip'. I believe reading the symbol table is | quite straightforward, the main problem being that on Unix | you don't actually know where the binary lives, so you have | to wire it in or search the PATH. | | Another problem is that you don't normally link a *complete* | copy of the base package into your binary, you only link the | bits you need. Linking the whole lot would mean every binary | would be about 10M; but doing this on the basis of a flag | which you turn on when you want to do dynamic linking maybe | isn't so bad. There is another option too, which I find quite attractive. To the interface that Simon mentioned: | loadLibrary :: FilePath -> IO () | lookupEntity :: String -> IO a add one more call: addEntity :: String -> a -> IO () The effect is to extend GHCi's dynamic linker's symbol table with an extra binding. So that 'lookupEntity' of the same string would return the value you stuffed in with addEntity. Why is this useful? Because it enables the 'main Haskell program' to populate the symbol table with the symbols that the plugins need. I'm guessing that the dynamically loaded plugins will not need very many entry points to the main program, so the 'populate symbol table' code would look like do { addEntity "foo" foo ; addEntity "baz" baz; ..etc.. One nice feature is that this automatically makes sure that the main program mentions 'foo', 'baz' etc, even if only the plugin is meant to call them. So that makes sure that when linking the main program, all the relevant bits are linked in. (Simon mentioned this problem in his message.) This approach is v simple, it would satisfy Duncan's need (I believe), it could be made more secure using dynamic types (addEntity and lookupEntity are good moments to typecheck), and it doesn't suffer from the disadvantages that Simon M mentioned. Simon PS: I'm working on an upgrade to GHC which, among other things, happens to eliminate the need for initLinker

On Wed, 28 Aug 2002 12:20:31 +0100
"Simon Peyton-Jones"
There is another option too, which I find quite attractive. To the interface that Simon mentioned:
| loadLibrary :: FilePath -> IO () | lookupEntity :: String -> IO a
add one more call:
addEntity :: String -> a -> IO ()
The effect is to extend GHCi's dynamic linker's symbol table with an extra binding. So that 'lookupEntity' of the same string would return the value you stuffed in with addEntity.
One nice feature is that this automatically makes sure that the main program mentions 'foo', 'baz' etc, even if only the plugin is meant to call them. So that makes sure that when linking the main program, all the relevant bits are linked in. (Simon mentioned this problem in his message.)
You mean that the API module won't accidentaly get identified as dead code and removed at link time. (which is nice :-) )
This approach is v simple, it would satisfy Duncan's need (I believe),
Simple is good!
it could be made more secure using dynamic types (addEntity and lookupEntity are good moments to typecheck), and it doesn't suffer from the disadvantages that Simon M mentioned.
We still have the problem that some modules need to be loaded in their entirity or suffer from loading things multiple times and the wierdness that goes with that? To allow sharing of whole packages really would require access to the symbol table, I suppose, since a package contains loads of symbols. For what I want to do however this is probably ok since plugins probably shouldn't be using stdin/stdout anyway. Are there any more serious issues with loading two copies of the standard libs? Also, is there any way of identifying the dependancies of a ghc-generated .o file, or does ghci use the .hi files? If people think this is the right approach(tm) and it's possible to implement without being a ghc uberhacker then I'll have a go - any assistance welcome of course. (What have I let myself in for!) Duncan
participants (2)
-
Duncan Coutts
-
Simon Peyton-Jones