Writing GUI in one language and main app in another
Let's say I write an app in Haskell or Erlang (or any other, doesn't matter) and I want it to work with my gui in a more gui-friendly language (my opinion) let's say P开发者_开发知识库ython. How to glue those two? How would you communicate between those two parts of application? Making some kind of a server or something? Is this kind of solution popular? I've seen things like SMplayer which is a gui for mplayer and it works pretty good. What are your thoughts on this kind of design?
I have written applications in Haskell using both methods (client/server, native) and they both come with their {dis}advantages. I realize this is more that you asked for but I have documented the upsides and downsides of both approaches in the hopes that it will help you make a more informed decision.
More specifically the approaches I used were:
- Web applications that use Haskell as the backend and Javascript/HTML for the frontend. Communication was done solely using JSON. No HTML or Javascript was generated on the backend.
- Natively in pure Haskell using GTK2HS
The upsides of the first approach are:
- I was forced to separate GUI code from back end logic. It definitely made for cleaner design.
- Haskell now has high-performance webservers [4,5]. It also has great CGI/FastCGI and database support if you want to write PHP-style scripts on third-party webservers. I used the latter approach and it worked pretty well.
- UI libraries are good enough now where building a front-end in Javascript is quite a pleasant experience. I am very happy with Qooxdoo [2] but there are several options (jQuery, ExtJS ...)
- Software Transactional Memory [3] makes it trivial to store concurrently accessed state on the server side. STM is the single biggest reason that this approach is viable and fun.
- I liked that the UI was consistent and easily deployable to any platforms that could run a web browser. If your app has to run on Mac as well as Windows and Linux I still think this is the best way to go (more below).
The downsides of the first approach are:
- I had to deal with authentication and sessions even when I knew that this was a single user application. There are now frameworks (Yesod, Happstack ...) that help with this but I think it is accidental complexity that can be avoided by writing a native application.
- I had to roll my own client/server communication protocol. Extending the protocol and making sure it was correct was painful on the Javascript end, but was an absolute joy on the Haskell end. I suspect this will be the case for any GUI-friendly-language/Haskell combination you choose.
- A good chunk of my code ended up just marshalling and unmarshalling JSON data. This is less of a problem now because I think there are a number of Haskell libs to that claim to automate this [1].
- Most hosts don't support Haskell applications.
The upsides of second approach are:
- all your development is in the same language and so it is easier to test.
- Glade is a great for visually building GUI's and Haskell integration is extremely good.
- deployment on Windows and Linux is easy.
- GTK2HS is very good, complete and well documented.
- The bindings also try to mirror the OO structure of GTK itself. There are downsides to this (see below) but the great advantage is that I was able to use documentation for other language bindings to fill in any documentation gaps. When I developed I was constantly referring to Python's excellent GTK docs.
The downsides of the second approach are:
- deploying a GTK2HS application on a Mac is god-awful and it looks ugly to boot.
- Installing GTK2HS on Windows is non-trivial, on Mac it is an open research problem.
- GTK2HS requires you to write very unidiomatic Haskell. There's mutable state all over the place and the lack of objects means that you're essentially writing procedural code.
Hope this wasn't TMI.
-deech
[1] http://www.google.co.uk/search?hl=en&as_sitesearch=hackage.haskell.org%2Fpackage&as_q=json
[2] http://www.qooxdoo.org
[3] http://www.haskell.org/haskellwiki/Software_transactional_memory
[4] http://hackage.haskell.org/package/warp-0.3.2.3
[5] http://snapframework.com/
You could do this:
- the core program in Haskell or Erlang can be run on its own on the command line, with a console prompt, etc.
- the GUI in any language starts the core program and drives it via the core's stdin and stdout.
This approach is used by gdb (core) / ddd (GUI). This lets you easily debug the core on the commande line. With this approach you can also easily do batch scripts using the core, unit tests, etc.
If by gui friendly language you mean having Visual GUI Designer, then you still can do it in haskell. 2 major linux GUI frameworks, GTK and QT have visual designers and you can use the GUI files they produce from haskell.
Check out gtk2hs or qthaskell libraries.
Thrift supports Haskell, Erlang and Python:
Thrift is a software framework for scalable cross-language services development. It combines a software stack with a code generation engine to build services that work efficiently and seamlessly between C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, and OCaml.
You have two obvious options:
- Put the entire app inside a single process. This would typically involve something like Windows DLLs (native, COM, managed assemblies etc.) or Unix shared objects.
- Communicate between the two parts of the app using IPC mechanisms.
Generally option 1 is preferable if the languages in question are amenable.
It is going to depend on the exact language you want to use both for the GUI and for the logic. As David answered, you basically only have those two choices, and they both have advantages and disadvantages:
Putting everything in a single app is the best performance-wise, because when you will make the calls to the other language, it will not wait until the other process will get control, and then will not wait for your process to gain control again to receive the answer. This is also the easiest solution if you can embed a language in another language, then they will by definition run in the same process.
Using different processes can be good if you are all the time doing a lot of things in the "logic" process, but want the gui to still be responsive. (although this could be achieved with threads too, in a single process). Also, if you can't embed the languages, this will be the easiest solution. (for example using simple sockets for IPC, which exist in almost all the languages and are truly portable. (which is not as true for things like pipes or shared memory)
So it really depends on the languages you will choose.
精彩评论