ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
How do you write a program that is independent of the UI (the functionality is a library, and you have, for example, CLI and GUI interfaces as separate apps).
The problem I have is how to report status and prompt the user from within UI-independent code? I could split it into parts that do not require any user interaction, but then most of the functionality will be in the UI, not the backend.
If it's a library, use callback functions. This is what e.g. PAM (pluggable authentication modules) do to enable conversation between any application and the PAM libraries.
If you already have a CLI application, you can write a GUI on top of it. The two can be separate processes, communicating via pipes (or named pipes or even UNIX domain sockets). If the GUI launches the CLI, normal pipes are the obvious choice; some popular media players such as mplayer and vlc support control this way.
If the application is a long-running service, and you want to have a GUI which attaches to and separates from the service cleanly, use named pipes or unix domain sockets for server-local communications, or perhaps UDP or TCP datagrams (locally via loopback) to allow a service with a GUI on a separate, networked machine. This is what e.g. MySQL does.
The real trick is to design the "conversation" so that it is easy to implement and to extend, while being simple and robust. One key point is to allow endpoints to parse (and ignore) unknown messages properly, without corrupting the conversation; this way future extensions are backwards compatible. With a library, you'd most likely use standardized binary data structures, but with other methods, text-based messaging is probably better - even with the increase in message size and the slight processing overhead. (With large amounts of binary data, tagged binary formats with a specific endianness is also a viable choice.)
Without further details, that's about as specific as I can get. Hope this helps,
Nominal Animal
Last edited by Nominal Animal; 03-21-2011 at 01:55 AM.
If it's a library, use callback functions. This is what e.g. PAM (pluggable authentication modules) do to enable conversation between any application and the PAM libraries.
That's a nice idea, but to be practical for something complex it seems like you have to use a language with strong support for closures and anonymous, first-class functions.
For example, we have a function that removes a list of files and has a parameter that takes a function to call for each failed file:
Code:
remove_files(list_of_files, func(file)
# create warning dialog, append to status dialog, or print message in terminal
endfunc)
Seems like this would be complex and difficult to manage if functions can only have fixed, global names and closures were not supported.
Absolutely correct. In fact, you don't even have to qualify with "if it's a library".
Quote:
That's a nice idea, but to be practical for something complex it seems like you have to use a language with strong support for closures and anonymous, first-class functions.
Horse hocky That's absurd, and untrue
Quote:
If you already have a CLI application, you can write a GUI on top of it.
Also a good idea, if the command-line program is not interactive. For example, "gcc" or "svn" would be excellent candidates; "vi" not so much
Here are two good Wikipedia articles that might be of interest:
I think paulsm4 brings up a significant point. A text-mode application that is just a run-and-done application that takes input from the commandline and/or environment and/or config files is a whole different animal from one that runs and interacts with a user. GUIs that are wrappers around the former type of application are somewhat common. For example, almost all of the GUI CD/DVD burner applications are simply wrapper code around the underlying cdrecord family of tools.
On the other hand, are applications that are interactive. These tend to have specific ideas about what resources they use to interact with users, and are probably not so easy to put wrappers around (some of the gdb GUIs would fit this class of application).
I would like the OP to provide some clarification on the question. The value of separating the base functionality of the code from the UI functionality seems clear. Is the question really about how to build such an architecture, or is the question about how to craft code which can be ported to differing flavors of UI support? In large part, I think the specific UI system will impose a structure to which your code will have to conform. Very often, this will take the form of event-driven handlers that you can code to respond to UI events such as keystrokes and pointer events. These are invariably UI-specific (eg, GTK, Motif, Qt, Windows, Tk, etc.). While they mostly tend to follow the same patterns, I doubt that it is practical to build in UI independence into an application. Some UI packages/libraries use a significantly different API pattern, such as curses.
What if you've got a complex function with a lot of state variables that are needed for handling callbacks from the library?
In C, it's the original callers responsibility to construct the state needed by the callback function prior to calling the library function, and to cleanup it after the library function exits. If the callback function may interrupt or cancel the operation, it is the responsibility of your callback function and your application to agree who does the cleanup then.
The library just does not care a whit.
An example library function with callback support in C:
Code:
struct file_information {
mode_t mode;
uid_t user;
gid_t group;
off_t st_size;
char const *const filename;
char const *const fullpath;
};
int multi_file_remove(const char *const pattern, int (*callback)(struct file_information *, void *), void *payload)
{
struct file_information *info;
int result;
/* ... A lot of setup work ... */
while (...) {
/* Construct the description of a file into info */
if (callback) {
result = callback(info, payload);
if (result) {
/* Callback function aborted the operation! */
/* ... Cleanup ... */
return result;
}
}
}
/* ... Some cleanup work ... */
return 0;
}
The interface is described by a header file that might look like
If nothing else, please see how the C library function qsort is implemented: your own program must supply a function that does the actual comparison. The library function just does the memory copies and comparisons in the most efficient order it can. You can compare structures literally megabytes in size, as complex as you ever wish. And it's a C89 function, practically ancient.
In a GUI application, the callbacks are typically asynchronous triggers or updates to fields or variables. And since most GUI APIs are easiest in C++ (or perhaps Python, take your pick), you can follow dugans advise and use the OOP features for even easier implementation. It has been done, and it's not really difficult.
Nominal Animal
Last edited by Nominal Animal; 03-21-2011 at 02:36 AM.
Reason: Post deleted as requested by Xav
To answer theNbomr's question, my question is how to make a highly interactive backend that would make it easy to write frontends such as plain command line, ncurses, GTK+, QtGui, etc.
Just wanted to point out that VLC seems to have already solved lot of these problems. It does have a surprising variety of "frontends" and interactive control methods. It might be worth your while to check out the sources.
Last edited by Nominal Animal; 03-21-2011 at 02:07 AM.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.