Journal Articles

CVu Journal Vol 12, #5 - Sep 2000 + Project Management
Browse in : All > Journals > CVu > 125 (21)
All > Topics > Management (95)
Any of these categories - All of these categories

Note: when you create a new publication type, the articles module will automatically use the templates user-display-[publicationtype].xt and user-summary-[publicationtype].xt. If those templates do not exist when you try to preview or display a new article, you'll get this warning :-) Please place your own templates in themes/yourtheme/modules/articles . The templates will get the extension .xt there.

Title: Visual Control and COM

Author: Administrator

Date: 03 September 2000 13:15:40 +01:00 or Sun, 03 September 2000 13:15:40 +01:00

Summary: 

The two leading document preparation systems used in academia are LaTeX (and related tools like LyX) under Unix or Linux, and Microsoft Word under Windows.

Body: 

The two leading document preparation systems used in academia are LaTeX (and related tools like LyX) under Unix or Linux, and Microsoft Word under Windows. These two programs epitomize two opposing philosophies. In LaTeX, preparing a document is like programming, where most of the low-level optimisations and presentation rules are taken care of by the compiler. In Word, much more of the presentation is taken care of by the user, and the user can manipulate it visually.

I personally prefer LaTeX, not least because I have a visual disability and using LaTeX gives me the assurance that my documents are visually well presented without my having to worry about it. Many Word users do not even know about some of the typesetting issues that LaTeX handles automatically. On the other hand, I have a sighted friend who strongly prefers Word, because she has mastered its visual interaction and wants more low-level control over the details. I had difficulty understanding this at first; why would anybody want to spend time and energy doing a computer's job, and commit themselves to one particular presentation in the bargain? Then I realised that my friend's natural way of thinking is highly visual; she has already done the presentation in her mind, and wants to transfer her mental image to the computer without changing it, almost like drawing (she handles diagrams with particularly impressive agility). She cannot accept a program like LaTeX that takes over the task of presentation for you, since specifying a document in a non-visual manner is unnatural to her.

The same control dichotomy is also prevalent on the World Wide Web. Tim Berners-Lee did not intend HTML to rigidly specify presentation, not even to commit itself to a visual output device, but page composing software uses many tricks to get around this; browser independence and accessibility are usually the first things to go. Such software exists because visually minded designers need visual control; without it, they would struggle.

This phenomenon also arises in GUI programming. "Visual programming" tools, which let you meticulously "paint" the user interface (rather than just get on with the code and let the GUI libraries work out how it looks on each set-up), are very popular, particularly under Windows. However, people who excel in using such tools are sometimes not so good at the non-visual aspects of programming, and for this reason, commercial software teams are sometimes made up of visual programmers sketching the front-ends of applications and using libraries that were written by their less-visual counterparts. This is where COM (Component Object Model) comes in; it is a glue that can bind the twain together.

COM is a de-facto language-independent standard that allows interfacing between binary components, so an application in a language like Visual Basic can call binary code in a DLL that was written in a language like C++. 32-bit Windows platforms rely heavily on COM; ports to other platforms are reportedly in progress. The basic idea, from a C++ point of view, is that your class (implementing a COM component) inherits from one or more "interfaces", which are abstract classes specifying (but not implementing) virtual methods that others may call in order to interact with an instance of your component.

Both your class and its interfaces have 128-bit GUIDs (globally unique identifiers); unfortunately the GUID generator uses your network address (hence introducing a needless requirement of a network connection), could be subject to clock roll-over problems, and still cannot guarantee that the GUIDs are collision-free (for example, what if two machines have the same network address at different times but one of the clocks is wrong?) However, cynics would say that there are enough bugs in Windows anyway for this one not to make much difference.

The Windows OLE (object linking and embedding) system keeps track of where your components are by storing their paths and GUIDs in the Windows registry. If you have ever played with regedit and wondered what HKEY_CLASSES_ROOT is, now you know. Note that the components are treated as a system-wide library, which might be updated by installing almost any Windows program; this is why installing some buggy programs can permanently reduce the stability of a system (my Word friend recently complained that her previously stable Windows 95 system now crashes incessantly since she asked me to upgrade Netscape, and this happens even when she does not run Netscape). Needless to say, cleaning up this situation is very difficult; even programs like InstallShield have trouble when components are used by more than one program. If you want a stable Windows system then you have to be very careful about what you install.

Perhaps unsurprisingly, writing a COM component involves writing lots of housekeeping code before you can start, as well as updating the system registry. But if you have access to a recent version of Visual C++, you can use one of the "wizards" to get you started - from an empty project, File/New defaults to "ATL/COM AppWizard", and once you have such a project you can use Insert / New ATL Object to add a component to it. Then right-click on the interface in the tree diagram, say "Add Method" and set its name and parameters (more on this below), then double click on the other occurrence of the interface in that diagram (by expanding the class you have created) and insert your code.

The parameters of your methods need special attention. You do not get to return anything other than a status code, so any data that is to be passed back to the application needs to be done via pointers (the system does not seem to like C++ references). The OLE system needs to know about what those pointers point to, so that it can marshallise (the Java term is "serialize") the data correctly for communicating between the applications. Therefore, the IDL (interface definition language) version of pointer declaration looks like this:

[in,out] int* someVal

This means that the single int pointed to by someVal is both an input and an output value, and should be marshallised in both directions. Some languages (like Visual Basic) discard changes made to the value; to get data back to them you may have to declare something as [out,retval] in which case it becomes a "return value" (as though it were the return value of the method). If it were an array, you specify size_is with a parameter; I could not find out what you are supposed to do for null-terminated strings.

When you build the project, the registry gets updated with the location of your DLL, and you can use it in Visual Basic by selecting it under Project/References, declaring your class in the general declarations section (e.g. Private obj As MyClass), creating an instance in the Form/Load section (e.g. Set obj = New MyClass) and calling its methods in the event handlers (e.g. obj.someFunc (Text1)). When you ship that application, your component should be included with it and the install and uninstall code should take care of the user's registry; of course, this does not really help with keeping YOUR registry tidy, nor does it help if you want to ship just the component for someone else to use. Personally, I have given up trying to keep my Windows system in good order; my primary operating environment is Linux, so I do not really mind what happens to my Windows partition anymore.

If, like me, you prefer to develop under a non-Windows platform and you do not want to tie your code to Windows, you can avoid it by using encapsulation. When you have to insert your code into the appropriate methods, do not really insert your code - just insert a function call or a method call, add appropriate #include directives (and maybe create an instance of your class within the COM class), and put the real code in separate files (included in the project). You can then develop your underlying code completely independently of Windows and COM, and the COM code just calls it. You might still need to use conditional compilation in places (for example, your command-line interface will probably not be compiled in to the COM version).

This solution is not satisfactory because you still need to use Windows and Visual C++ every single time you want to compile the COM version, not just initially. It is theoretically possible to take the code produced by the "wizard" and cross-compile it (together with the libraries) with Ming GCC under Linux, but some porting needs to be done because the libraries are not exactly standard C++. In my brief experiments, I fixed the case-sensitivity of filenames (using emacs' "dired" and symbolic links), the "backslash" line breaks in illegal places (using regexp search and replace), and the missing implementation macros (using my own defines), but I gave it up as a bad job when I hit the inline assembler.

Incidentally, you cannot run the Microsoft compiler under a Windows emulator such as Wine (even if it were technically possible, it actually violates Microsoft's license agreement to run their software on anything other than the operating system it was meant for). So, if you want to develop COM components for Windows developers then you may well end up having to use Windows yourself, at least in the build script. I do not like having to write build scripts that reboot the system. The DIY alternative to COM - get the GUI to execute command-line programs and communicate with them through temporary files - seems more straightforward, if less efficient.

Notes: 

More fields may be available via dynamicdata ..