General Design Issues

Here are three designs "templates" I considered for developing my application, in order of preference:
  1. Developing an application with everything in a single address space, without using EML.
  2. Developing an application that communicates with a Viewer through a running Session Manager via pipes from a non-EML based application.
  3. Developing an application that communicates with a running Viewer through a running Session Manager via pipes from an EML-based application with calls to my C++ library via a C++ Facade or Adaptor design pattern interface.
Note that, yes, there are other possible design configurations.  These are just the ones that I decided to iteratively try to use for developing my C++ application. 

As you might infer from the design order, I wanted to avoid using  EML.  EML hails from the bad old days when cross-platform GUI development was very, very hard.  ERDAS had to make their applications easily portable between UNIX and Windows based platforms.  (And, once upon time, even VAXen.)  As the old computer science adage goes, "most computer science problems can be solved by adding a layer of indirection".  EML was the layer of indirection developed by ERDAS to solve the cross-platform GUI problem.  Theoretically, all you'd have to do to port your application from, say, UNIX to Windows would be to copy the source to a suitable Windows development environment from your UNIX environment, re-compile and link, and your application would be ready for work in Windows.

However the bad ole days are over.  There exist tools to make easy writing portable GUI C++ applications, such as wxWindows and Qt.  I have a lot of experience with Qt, and so preferred to use that to develop my GUI.  Not only did I have a choice of a number of powerful GUI builders with Qt, but its system of signals and slots made it very easy to write event-driven applications.  Qt has also grown out of its GUI origins as it now provides network and XML services, among others. 

I hoped to eschew EML in favor of Qt and have lower level Imagine functions work inside of Qt widgets.  During the Developer's Toolkit course, I noted that EML was very brittle, in that that it was trivial for EML-based applications to crash during the edit-compile-test cycle.  Moreover the diagnostics were obtuse, if you got any at all.  (It was possible for applications to crash with no warning and leave no clue as to what happened in the session log.  If things really got wedged, you'd have to restart the Session Manager.)  Also, having to keep two separate files in sync made it easier to create programming errors; variable and function names had to be the same in both files, and so you'd have to watch that when you changed the name in one file that you did so in the other. 

To me, it's much easier to develop and maintain everything in a single language, and not to have to rely on source written in two languages.

First Whack: Single Address Space Model


Initially I tried technique #1.  For that, I noted that there seemed to exist a means of creating a Viewer by giving it a "handle" to a parent widget by calling this function:


extern Evue_DisplayHandle edis_CreateDisplayFromHandle __((
        Evue_Connection *apc,
        Emsc_Pointer    parent,
        Eui_BasePart *frame,
        Eerr_ErrorReport **err
));


So I:
  1. initialized Qt
  2. initialized the Toolkit
  3. created a link to the Session Manager
  4. created a simple Qt dialog
  5. opened a Viewer connection via evue_Open( "viewer", *error_report )
  6. called edis_CreateDisplayFromHandle()
Unfortunately this didn't work.  This seemed to really want the EML stuff initialized.  When I tried to initialize the EML library, it whined about not being able to find its "built-in DLLs" and bailed.

So, on to application design technique #2.

Second Whack: non-EML-based Application Communicating with Session Manager

I knew that Viewers communicated to other processes via pipes through a Session Manager.  All I'd have to do would be to send the right messages back and forth through a Session Manager pipe to interact with the Viewer.  Simple, right?

Unfortunately all the documentation is oriented towards EML applications, so the communication protocol isn't documented.  You can presumably infer it from reading header files and reverse engineering traffic as message packets are marshalled and unmarshalled.

In any case, that didn't stop me from trying.  So I:
  1. initialized Qt
  2. initialized the Toolkit
  3. created a link to the Session Manager via esmg_SessionConnect( argv[0], ESMG_SESSION_APPLICATION, *error_report );
  4. created a simple Qt dialog
  5. opened a Viewer connection via evue_Open( "viewer", *error_report )
  6. called Evue_DisplayHandle display_handle =
                evue_SelectViewer( imp_->viewerConnection.get(), "Select Viewer", *error_report );
Progess!  It actually did allow me to select a Viewer!  Unfortunately my application wedged.  I had to manually kill the application from the Session Manager.

I suspected, though, that there was probably some pipe related housekeeping that I wasn't doing that was causing my application to lock up after successfully calling evue_SelectViewer().  Further research unveiled esmg_ProcessExitHandlerRegister().  I created an empty process exit handler function and called esmg_ProcessExitHandlerRegister() with ESMG_PROCESS_EXIT_HANDLER_EACH_TIME.  Success!  The function call returned!  Unfortunately it only seemed to successfully get a handle on the viewer part of the time.  Clearly I needed to do more research to better understand the message passing protocol and associated semantics.

Unfortunately I didn't have the time to do this as I need to get something up and running ASAP. Still, I have high hopes that this scheme will work.  And, when it does, we can all throw off the EML yoke and more quickly and easily write maintainable GUI apps that talk to Imagine Viewers.

Third Whack: Modifying a Traditional EML-based Application to Use C++ Wrapper Classes

So, I'm left with scheme #3.  I've not given up on C++, though, especially since the "FeatureSpace" library I need to use in my project is already written in C++.  Besides, using C++ is so much better than ANSI C as  with C++ memory management is no longer a nightmare, and I have access to a powerful set of tools in the Standard C++ library, and other libraries, such as the Boost C++ Library.  In subsequent sessions I share issues related to writing C++ applications using the Toolkit and Toolkit related wrapper source code.

Note that I've developed a very basic C++ Imagine Wrapper Library that's suitable for use with this implementation method.