Hi, folks,
with this long and hairy mail I would like to clear some FUD which
happily proliferates on this maillist. I will try to show you that it's
possible to use dynamic linking easily, that it allows for multiple
drivers, does NOT require anything to be hardcoded and that it's The
Right Way To Go (tm)
- first of all, dynamic linking on Linux works well. I have already
tried loading drivers with it (not for lcd) and it works like a charm.
- apache historically used static linking but it usually uses dynamic
linking now. Modules define table with function pointers just as I
showed you
- netscape httpd used similar approach, with entry points and .so files
named in config file
- there's no problem having driver specific prefix for entry points,
since you can name that prefix in config file too. On the other hand,
single entry point name for all drivers will prevent static linking (and
does not work on Windoze, AFAIK)
That said, the drivers could be used like this with lcd:
File lcd.conf:
[main]
driver_dir=/usr/lib/lcd
driver_list=mtxorb,hd4478,lirc
[driver_mtxorb]
lib=mtxorb.so
[driver_hd4478]
lib=hd4478drv.so
options=use_quick_parport
[driver_lirc]
lib=lirc.so
[display_main]
driver=hd4478
device=/dev/whatever0
size=16x2
[display_bigone]
driver=mtxorb
device=/dev/whatever34
size=20x4
options=backlight,......
[display_small]
driver=hd4478
device=/dev/whatever45
size=16x1
[app_lcdecho]
display=display_main
Ok. Now for example hd4478drv.c:
#include <lcd_plugin_api.h>
#include <lcd_display.h>
Lcd_Plugin_API hd4478_api = {
TYPE_OUTPUT,
hd4478_open,
hd4478_close,
hd4478_flush,
};
int hd4478_open (Display *display) {
/* opens device display->device, fills in display */
}
int hd4478_close (Display *display) {
}
int hd4478_flush (Display *display) {
/* takes framebuffer from the display and flushes it to the hd4478
LCD display */
}
static char some_fn () {
}
And now for example lcd_echo.c, simple proggie to display string on any
one display attached to the system:
Usage:lcd_echo -d <display_name> <string_to_display>
....
int main (int argc, char **argv) {
/* reads display_name and string_to_display */
parse_params (argc, argv);
ini_open (config_file);
driver_name = ini_get_key_in_section ("display_"+display_name,
"driver", NULL);
lib_name = ini_get_key_in_section ("driver_"+driver_name, "lib", NULL);
lib_api_name = driver_name + "_api";
hnd = dlopen (lib_name, RTLD_LOCAL);
api = dlsym (hnd, lib_api_name);
/* malloces Display struct and fills it's fields like device, size
etc. */
display = new_display (display_name);
api->open (display);
display_write (display, string_to_display);
api->flush (display);
api->close (display);
ini_close ();
}
(Note: I use string+string in this pseudocode to avoid mallocs and
strcats. Also no checking is done)
Why to use api tables at all? One reason is that data objects are not
subject to name mangling when linking with C++
What do you think?
Jarda Benkovsky
-----------------------------------------------------------
To unsubscribe from this list send a blank message to
lcdproc-unsubscribe@lists.omnipotent.net