dlhack()
In my living room, there's a TV, with a computer connected to it.
In that computer, there's a DVD-ROM player, a hard disk, and a card with a TV output.
On that hard disk, there's Debian with xine to view DVDs
When I originally put it there, I would pick up the keyboard to do some user input. This works, but a keyboard is klunky. So, instead, I've been working on jsxine, a little application that does not much more than open a window, and tell xine to play a DVD there, but use the joystick for UI[1]. My 'joystick' is a Logitech Wingman Gamepad Extreme, which has a cable long enough for me to be able to use it comfortably from the couch, so I can use it as a sort of remote control.
The current version has quite some things hardcoded: button 0 is 'select', button 5 is 'eject', button 6 'previous chapter', button 7 'next chapter', and button 8 is 'start or stop playing'. The primary two axes move around in the DVD menu; and other stuff is not yet implemented. This layout, of course, makes a lot of sense on this particular gamepad, but I doubt it does on other joystick devices. And since I want this to eventually be useful for other people, too, I recognized that I would need some way to configure things.
My initial stab at configuration would create a hash table of available actions, read out a configuration file, and then find the appropriate function pointer in the hash table. While this works, it has one rather important downside: adding a configurable action would requrie another item in the hash table; this would eventually make the hash table horribly long. So I thought, why not use the configuration value to ask the dynamic linker to get me a function pointer?
With a little help from my friends, that's exactly what I did. Proof-of-concept code:
#include <dlfcn.h> #include <stdio.h> int function() { printf("In function!\n"); } int main(int argc, char**argv) { int (*funcptr)(void); void* handle; printf("foo\n"); handle = dlopen(NULL, RTLD_NOW); funcptr = dlsym(handle, "function"); funcptr(); return 0; }
Compile with cc -ldl -rdynamic. Et voila, that gets you an application which can do a lookup of function names at run time.
Long live C.
Of course, there's a bit of a danger in the above example. A user could just write a config file that has things like 'open' and/or 'write' as arguments, or the like. One should make sure that it can be obvious from the function name that it does indeed define an action; for example, by giving them a common prefix, and prepending that prefix to the function name before handing the name off to dlsym().
But other than that, this seems to work. It apparently also is documented in the FreeBSD documentation on dlopen(), so maybe it's not as much a hack as I thought...
Oh well.
Note that on GNU systems, you can also put a #define _GNU_SOURCE before the #include <dlfcn.h>, you can drop the dlopen() call and go straight to dlsym(), with RTLD_DEFAULT as the handle.
[1] Yes, I could have done a Xine plugin. I didn't want to. This is as much a project to produce something useful as it is a project to hack and have fun.
“FreeBSD documentation”? How about man 3 dlopen?
It's not a hack at all (apart from your use case, of course). That's the way you use a dynamic module in C. (i.e. python and the like will do this when you type "import", as long as it's a C module)
Scares me to death when I hear such stuff from a "DD from 2001". :[
-- A Debian User.
There are quite a few problems with your idea. The first is that by default symbols should not be visible unless they are to be called from outside, it has very bad performances and all in all it's quite silly to do it this way.
But beside that, I'm sure I have seen a few different software that can simulate keypresses from the keyboard through the user event interface of the kernel with a joystick, and thus you should just need to wire it down with the original xine-ui.
Or use gxine and the gxine_client program to control it.
Or in general think not of doing things that tend to be quite some hacks and you should not suggest people to follow for your own karma...
Note: it's trivial to make the hash table auto-generate starting from the source functions, check out zile as an example of that with its lisp-like bindings.
And just saying something from the xine developer point of view (which I am): no we absolutely don't want this as a xine plugin!
Hm. I cannot find this in http://www.FreeBSD.org/cgi/man.cgi?query=dlopen&apropos=0&sektion=0&manpath=FreeBSD+7.1-RELEASE&format=html
Oh well… the RTLD_DEFAULT thing works on MirBSD too, but you probably should use RTLD_SELF instead, for similar reasons like the one you mentioned. (Nice trick though, btw.)
One note: there is no -rdynamic either on Kubuntu (at work… don't ask, not my choice) not MirBSD, but -Wl,-E works fine.
Groeten //mirabilos