TweetFollow Us on Twitter

Portability
Volume Number:9
Issue Number:10
Column Tag:Software design

Related Info: Memory Manager File Manager

Beyond the Macintosh

Here’s a way to design your code to be portable

By Lala “Red” Dutta, DataViz, Inc.

Here we are... 1993 and the playing field has narrowed down to a handful of machines and architectures. The contenders left on the field are Unix boxes, PC’s and Mac’s. However, soon to enter the playing field is the Power PC based Macintosh. And where are we? Since the majority of MacTech readers are Macintosh programmers, it is safe to assume... “We’re On A Macintosh!” (And I say that while making some Tim Allen grunts)

But for a moment, let me state a few observations of mine...

• Macintosh programmers know what the game really is... “Make something obvious and simple, and people will use it.”

• Wouldn’t it be nice if we could show the rest of the world how to write a better application?

• Wouldn’t it be nice if we made lots of money selling this stuff to the unenlightend?

So with those observations, let me ask the million dollar questions... Is your code portable? Will you be able to recompile and run on the Power PC? And what about Windows and OS/2? Can you recompile and run there too? After all, if you can do that, you can make money on many fronts!!! (Mo’ Money, Mo’ Money, Mo’ Money!)

At this time, I want to make a couple of statements about what’s up and coming, and what’s not! A lot of gratuitous code will not be present! After all, we’re all adults, and we’re bright enough to code this stuff on our own! (We don’t need no stink’in code!) You can also expect to see quotes from many movies and sitcoms. Also, even if you’re not a techie, you should have no problem understanding the gist of what I’ll be talking about (although a vague idea about C and C++ would help).

Zen And Portability

Before we can walk down the golden path, we need to have an objective. So here is the line my co-workers are use to hearing me say...

If truly portable code is written, it can be used anywhere, any time, and in any form.

So there’s the target we wish to hit. But now to get back to the real world, we know we can’t hit that 100% of the time. So the true key is to separate what can hit that target from that stuff which cannot. To get a little more specific, we need to achieve the following:

• Create platform independent code that relies on other platform dependent code to do the dirty work.

• Have uniform API’s between the platform dependent and independent code.

• Ensure that the platform independent code is completely insensitive to the underlying hardware and operating environment.

• Ensure that the platform dependent code has a completely general interface and takes full advantage of the underlying hardware and operating environment.

• Finally, ensure that portability is retained through maintenance.

Portability Overview

So what does this all mean? Hopefully, this diagram clears things up a little bit:

With this type of model, your core code deals with doing the main task at hand. It then relies on other code to take care of the platform specific stuff. So what kind of things go in each group of code? It really is entirely your choice, but this happens to be my model:

Environment Manager TApplication, InitApp, MaxApplZone

User Interface Manager TWindow, TLists, TButton, TStatic,

DrawRect, DrawCircle, Line, etc...

I/O Manager NewFile, OpenFile, CloseFile, Read,

Write, Seek, Tell, etc..

Memory Manager AllocHandle, FreeHandle,

AppendToHandle, HandleSize, etc...

Another preference of mine is to have C++ classes and objects in the Environment and User Interface managers. Also, I prefer standard C routines for I/O and Memory Management. However, you can do whatever you are comfortable with.

Finally, I prefer to keep sub-folders (or sub-directories that contain the non-portable code. This way my main folder (or directory) contains only the portable code. I also prefer keeping everything on a Macintosh server (because of resource forks). Then I can have a batch file that mounts the volumes that contain all the code, copies what I need, and starts the makefile. On the Mac, I can just use a makefile.

Portable Data Types

One of the most prevalent problems in portability is data. (Red’s proverb on cross-platform computing: “one machine’s garbage is another machine’s data.”) What do I mean... byte order and data size. The Motorola and Intel chips store numbers in reverse order from each other. For example, lets say I have a long unsigned integer with the value 110 (hex 6E). On the Motorola, it would exist as 0x0000006E. On an Intel machine, it would exist as 0x6E000000.

Another problem to keep in mind is the size of data types. For instance, what is the size of an ‘int’ under MPW, Think, or Microsoft? Are they all the same size? And moreover, what is the size of a ‘double’ under all those compilers?

And now for the clinchers... is a Handle always a pointer to a pointer? Is a Handle always four bytes? Does a pointer always point to the right segment?

So how do we get around these problems. Actually, the solution is pretty easy. What you need a set of data types that have the same meaning regardless of their native environment. You can achieve this by having an include file (I usually call it defTypes.h) for each platform which defines some standard types:

Byte Single byte signed character

UByte Unsigned single byte

Word Two byte signed integer

UWord Two byte unsigned integer

Long Four Byte signed integer

ULong Four Byte unsigned integer

Float64 64 bit IEEE Float

Float80 80 bit IEEE Float

Pointer Pointer to an absolute address

Handle Token for relocatable space

etc...

Now lets take some real world examples. If I were under Think C and I had to use 64 bit IEEE floats, I would typedef Float64 as a short double. If I were under MPW and I needed a two byte integer I would typedef Word as a short. If I needed a pointer under Borland C, I would typedef Pointer as a (void far *). This way I can have a known data type and definition under each platform.

Additionally, I have routines that take a Pointer to a certain data type and returns the data in its native form. These routines include:

/* 1 */

Word            macword(Pointer p);
Long             maclong(Pointer p);
Float64        macFloat64(Pointer p);
Float80        macFloat80(Pointer p);
etc...
Word            pcword(Pointer p);
Long             pclong(Pointer p);
etc...

Each routine describes the type of data it uses as an argument. For example whenever I use the function pcFloat64, I’m saying that the thing p points to is a 64 bit pc based IEEE float and I want a native 64 bit float returned. So what does the code look like?

/* 2 */

// Borland Implementation of pcFloat64
Float64 pcFloat64(Pointer p)
{
 return *((Float64 *) p);
}


// MPW Implementation of pcFloat64
Float64 pcFloat64(Pointer p)
{
 Float64f;

 revmem(p, (Pointer) &f, 8);// reverses p onto f
 return f;
}

Notice how the Macintosh implementation needed to reverse the data in order to use it. And since the PC implementation already had it in its required form, it merely sent the value along.

Finally, how do we manipulate this data. Generally, I have a library of platform independent routines that do the following:

/* 3 */

myGetc(TBuff)  Get one byte from a buffer
myGetN(TBuff, Ptr, Word)  Get n bytes, put it at Ptr
myGetw(TBuff)  Get a word from a buffer
myGetl(TBuff)  Get a long from a buffer
etc...
myPutc(TBuff, Byte)Put one byte into a buffer
myPutN(TBuff, Ptr, Word)  Put n bytes into a buffer
myPutw(TBuff, Word)Put a word into a buffer
myPutl(TBuff, Long)Put a long into a buffer
etc...
// TBuff is a C++ class

Inside each of these routines, they would read the data in it’s actual form, and return the value in it’s native (or default form). So lets look at the following platform independent code that fetches a long integer from a pc based spreadsheet file:

/* 4 */

Long  myGetl(TBuff b)
{
 UByte  d[4];
 Long x;

 myGetN(b, (Pointer) d, (Word) 4);
 x = pclong((Pointer) d);

 return x;
}

Remember this code is platform independent! However, it does call pclong which has a platform independent interface, and platform dependent code.

Code Fragments And Re-Entrancy

Of course there is more to life than just applications. In the real world there are code resources, shared libraries, and dynamically loaded libraries. These code fragments are really good for localization or creating sub-applications. Or even if you wanted to create different libraries that several applications could share, they are good for that too. The topic of re-entrancy becomes prevalent if you are talking about having several applications share code at run-time. At that point, you cannot have any critical global data. (Not gonna do it! Can’t do it! Wouldn’t be prudent! Thousand Points of Light!)

But back to the issue at hand, we need to break these things down into their portable and non-portable parts and still be able to build these things as any of the three types of code fragments. Also, to be able to build code as any of the three types, we need to satisfy the most stringent requirements of all three. So let’s discuss some of the requirements of each of these types of code fragments:

Code Resources - One main entry point and must be under 32K. Also, under MPW it cannot have global data space. While under Think it may use global data space.

DLLs - Can have multiple entry points and can have global data.

Shared Libraries - These are equivalent to DLLs, but are only available under MPW. The biggie is that it will be available on the PowerPC.

So what are the overall requirements? We need code that has no global data space and is under 32K. Furthermore, it can have only one entry point. This isn’t too bad. If anybody has written any control panel devices you know how to get away without using global data and having only one entry point. Furthermore, we can also break our big code fragments into several smaller fragments. After all, isn’t that the definition of a code fragment? So we’re going to use the Macintosh Control Panel as our overall model.

But how do you do it? Well, this takes a little more finesse. Let’s go back to our original diagram of platform independent code. But now imagine that we put a platform specific front end (and export module for shared libraries). Also, we must create a standard calling sequence for using these fragments. I prefer the calling sequence described below:

OSErr fragMain (Word instruction, Pointer ctlStruct)

I use instructions for things like fragOpen, fragClose, fragDoTask, etc., and I use ctlStruct as a bucket for whatever I want to pass into and out of a fragment. Here is an example of a ctlStruct:

/* 5 */

typedef struct fragCtl {
 Word   paramCnt;
 PointerparamList;
 Handle fragWorkSpace;
} fragCtl;

And the way the fragMain would be laid out is as follows:

/* 6 */

OSErr fragMain (Word instruction, Pointer ctlStruct)
{
 OSErr  rc = noErr;

 switch (instruction) {
 case fragOpen:
 ctlStruct->fragWorkSpace = 
 AllocHandle (sizeof(mySpace));
 rc = MemErr();
 break;
 case fragClose:
 FreeHandle(ctlStruct->fragWorkSpace);
 rc = MemErr();
 break;
 case ...
 case ...
 default:
 rc = unknownFragInstruction;
 break;
 };

 return rc;
}

Remember you are free to have any types of calls you want. I’m just giving you an example of what can be done. At any rate, now that we have platform independent code for a fragment, how do we construct this stuff in the fragment type we need? Actually, this is the easy part. I have a header file that gets included that simple states the following:

/* 7 */

// Think C fragment Front End
#ifdef CodeResource
OSErr main (Word instruction, Pointer ctlStruct)
{
 Handle self;
 OSErr  rc;

 RememberA0();
 SetUpA4();
 asm  {
 _RecoverHandle
 move.l a0,self
 }
 HLock(self);  /* Don't move while running   */

 rc = fragMain (instruction, ctlStruct);

 HUnlock(self);
 RestoreA4();

 return rc;
}
#endif

And as far as shared libraries are concerned, I have a file called fragMain.exp which contains:

exports = extern fragMain;

For more details on Apple’s Shared Library Manager, you can contact Apple’s Developer Support.

Non-Portable Code

Let’s take a quick look back at our assertion about non-portable code. That assertion was to “insure that the platform dependent code has a completely general interface and takes full advantage of the underlying hardware and operating environment.”

Let’s also look back at the example of the pcFloat64 code. This is a good example of code that is platform dependent, yet has a completely platform independent interface. This makes life easy for the caller.

Now I want to take that concept one step further. Let's say I am working on the user interface part of my application. What I want is to create a TButton class for each platform that implements a regular push button. After all, I want to use push buttons. To get really specific, let’s look at Borland’s Object Windows Library.

Wouldn’t it be nice if we could have Borland’s OWL on all platforms? Actually, we can! All it takes is us rolling up our sleeves a little and creating these UI Libraries for all of the platforms we wish to support. Overall, we want C++ objects for the following user interface metaphors:

TWindow Put up a blank window

TMenu Object for a menu list

TPopUp Object for a pop up list

TScrollList Object for a scroll list

TList Create a list for scrolling, pop ups...

TCheckBox Standard check boxes

TButton Standard push buttons

TRadioButton Standard radio buttons

etc...

These C++ classes should have member functions that do whatever it is that you want. For instance, let’s take TButton. For TButton you need a constructor, a destructor, a hilite metaphor, disable metaphor, enable, and whatever else you may want.

You can take the same principles and extrapolate them for file management and memory management. However with those items, I prefer having straight C routines instead of C++ classes. (Give it to me straight Doc!)

Portable Code

Believe it or not, at this point, writing platform independent code is almost elementary. The only thing you need to do is to call your UI Manager for user interface work, call your file manager for I/O, call your memory manager for memory usage, and don’t call anything platform specific.

I know you’re saying “easier said than done.” At first it is easier said than done. But once your libraries are created, the problem is much easier the next round. Moreover, once you get into the habit, it becomes very easy. And the knowledge of what is portable, and what is not becomes more apparent. Moreover, I hope I have given you some ideas to think about and some plans to go cross-platform. And for the big Macintosh payoff, hopefully, you can position yourself well so compiling for the native PowerPC is trivial.

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Apple High Sierra 10.13 - The latest OS...
macOS High Sierra introduces new core technologies that improve the most important functions of your Mac. From rearchitecting how it stores your data to improving the efficiency of video streaming to... Read more
ScreenFlow 7.1 - Create screen recording...
ScreenFlow is powerful, easy-to-use screencasting software for the Mac. With ScreenFlow you can record the contents of your entire monitor while also capturing your video camera, microphone and your... Read more
Airmail 3.5 - Powerful, minimal email cl...
Airmail is an mail client with fast performance and intuitive interaction. Support for iCloud, MS Exchange, Gmail, Google Apps, IMAP, POP3, Yahoo!, AOL, Outlook.com, Live.com. Airmail was designed... Read more
CleanMyMac 3.9.0 - $39.95
CleanMyMac makes space for the things you love. Sporting a range of ingenious new features, CleanMyMac lets you safely and intelligently scan and clean your entire system, delete large, unused files... Read more
Numi 3.17.2 - Menu-bar calculator suppor...
Numi is a calculator that magically combines calculations with text, and allows you to freely share your computations. Numi combines text editor and calculator Support plain English. For example, '5... Read more
OmniGraffle 7.4.3 - Create diagrams, flo...
OmniGraffle helps you draw beautiful diagrams, family trees, flow charts, org charts, layouts, and (mathematically speaking) any other directed or non-directed graphs. We've had people use Graffle to... Read more
ExpanDrive 6.1.0 - Access cloud storage...
ExpanDrive builds cloud storage in every application, acts just like a USB drive plugged into your Mac. With ExpanDrive, you can securely access any remote file server directly from the Finder or... Read more
VueScan 9.5.86 - Scanner software with a...
VueScan is a scanning program that works with most high-quality flatbed and film scanners to produce scans that have excellent color fidelity and color balance. VueScan is easy to use, and has... Read more
Cocktail 11.0 - General maintenance and...
Cocktail is a general purpose utility for macOS that lets you clean, repair and optimize your Mac. It is a powerful digital toolset that helps hundreds of thousands of Mac users around the world get... Read more
OmniGraffle Pro 7.4.3 - Create diagrams,...
OmniGraffle Pro helps you draw beautiful diagrams, family trees, flow charts, org charts, layouts, and (mathematically speaking) any other directed or non-directed graphs. We've had people use... Read more

Morphite guide - how to explore like a p...
The much anticipated space exploration game, Morphite, has finally arrived, and we can't get enough of it. The game is essentially everything we wanted No Man's Sky to be. It's a game that puts a heavy focus on exploring foreign worlds, but the... | Read more »
The best visual novels on mobile
Narrative games have been around for ages, but only now have they been creeping into the mainstream spotlight. These games tell some of the industry's finest stories, and they break new ground in terms of gameplay and mechanics regularly. Here are... | Read more »
The best new games we played this week -...
It's pretty much been one big release after another. We were privy to a bunch of surprises this week, with a lot of games we'd been waiting for quite some time dropping unexpectedly. We hope you're free this weekend, because there is a lot for... | Read more »
Stormbound: Kingdom Wars guide - how to...
Stormbound: Kingdom Wars is an excellent new RTS turned card battler out now on iOS and Android. Lovers of strategy will get a lot of enjoyment out of Stormbound's chess-like mechanics, and it's cardbased units are perfect for anyone who loves the... | Read more »
The best AR apps and games on iOS right...
iOS 11 has officially launched, and with it comes Apple's ARKit, a helpful framework that makes it easier than ever for developers to create mobile AR experiences. To celebrate the occassion, we're featuring some of the best AR apps and games on... | Read more »
Phoenix Wright: Ace Attorney - Spirit of...
Phoenix Wright: Ace Attorney - Spirit of Justice 1.00.00 Device: iOS Universal Category: Games Price: $.99, Version: 1.00.00 (iTunes) Description: ************************************************※IMPORTANT※・Please read the “When... | Read more »
Kpressor (Utilities)
Kpressor 1.0.0 Device: iOS Universal Category: Utilities Price: $4.99, Version: 1.0.0 (iTunes) Description: The ultimate ZIP compression application for iPhone and iPad. - Full integration of iOS 11 with support for multitasking.-... | Read more »
Find out how you can save £35 and win a...
Nothing raises excitement like a good competition, and we’re thrilled to announce our latest contest. We’ll be sending one lucky reader and a friend to the Summoners War World Arena Championship at Le Comedia in Paris on October 7th. It’s the... | Read more »
Another Lost Phone: Laura's Story...
Another Lost Phone: Laura's Story 1.0 Device: iOS Universal Category: Games Price: $2.99, Version: 1.0 (iTunes) Description: Another Lost Phone is a game about exploring the social life of a young woman whose phone you have just... | Read more »
The Witness (Games)
The Witness 1.0 Device: iOS Universal Category: Games Price: $9.99, Version: 1.0 (iTunes) Description: You wake up, alone, on a strange island full of puzzles that will challenge and surprise you. You don't remember who you are, and... | Read more »

Price Scanner via MacPrices.net

Snag a Certified Refurbished Apple Pencil for...
Apple has Certified Refurbished Apple Pencils available for $85 including free shipping. Their price is $14 off MSRP, and it’s the lowest price available for a Pencil. Read more
12-inch 64GB iPad Pro on sale for $749, save...
Adorama has 12″ 64GB iPad Pros on sale today for $749 including free shipping plus NY & NJ sales tax only. Their price is $50 off MSRP. Read more
Apple Certified Refurbished iPad minis availa...
Apple has Certified Refurbished 128GB iPad minis available today for $339 including free shipping. Apple’s standard one-year warranty is included. Their price is $60 off MSRP. Read more
12-inch 1.2GHz Retina MacBook Pros on sale fo...
B&H Photo has 2017 12″ 1.2GHz Retina MacBooks on sale for $100 off MSRP. Shipping is free, and B&H charges sales tax in NY & NJ only: 12″ 1.2GHz Space Gray MacBook: $1199 $100 off MSRP 12... Read more
Sunday sale: 13-inch 3.1GHz MacBook Pros for...
Amazon has 2017 13″ 3.1GHz MacBook Pros on sale today for up to $150 off MSRP, each including free shipping: – 13″ 3.1GHz/256GB Space Gray MacBook Pro (MPXV2LL/A): $1649.99 $150 off MSRP – 13″ 3.1GHz... Read more
Looking for a 2017 12″ Retina MacBook? Save $...
Apple has Certified Refurbished 2017 12″ Retina MacBooks available for $200-$240 off the cost of new models. Apple will include a standard one-year warranty with each MacBook, and shipping is free.... Read more
Apple Offering Up To $455 Credit Toward iPhon...
iPhone 8 and 8 Plus are now available at the Apple Store, and you can receive up to $375 credit toward a new iPhone purchase when you trade in your eligible smartphone. Photo Courtesy Apple Just... Read more
AnyTrans Offers iOS Users Three Ways For Movi...
iMobie Inc. today announceed AnyTrans v6.0.1, which now can help iOS users move all data to iPhone 8/8 Plus seamlessly. The software is available both on Mac and Windows and fully able to move all... Read more
Snag a 13-inch 2.3GHz MacBook Pro for $100 of...
B&H Photo has 2017 13″ 2.3GHz MacBook Pros in stock today and on sale for $100 off MSRP, each including free shipping plus NY & NJ sales tax only: – 13-inch 2.3GHz/128GB Space Gray MacBook... Read more
Verizon offers new iPhone 8 for $100-$300 off...
Verizon is offering the new iPhone 8 for up to $300 off MSRP with an eligible trade-in: • $300 off: iPhone 6S/6S Plus/7/7 Plus, Google Pixel XL, LG G6, Moto Z2 Force, Samsung Galaxy S7/S7 edge/S8/S8... Read more

Jobs Board

Development Operations and Site Reliability E...
Development Operations and Site Reliability Engineer, Apple Payment Gateway Job Number: 57572631 Santa Clara Valley, California, United States Posted: Jul. 27, 2017 Read more
Data Engineer - *Apple* Media Products - Ap...
Job Summary Apple is seeking a highly skilled data engineer to join the Data Engineering team within Apple Media Products. AMP (home to Apple Music, App Read more
Development Operations and Site Reliability E...
Development Operations and Site Reliability Engineer, Apple Payment Gateway Job Number: 57572631 Santa Clara Valley, California, United States Posted: Jul. 27, 2017 Read more
Development Operations and Site Reliability E...
Development Operations and Site Reliability Engineer, Apple Payment Gateway Job Number: 57572631 Santa Clara Valley, California, United States Posted: Jul. 27, 2017 Read more
*Apple* Retail - Multiple Positions - Apple,...
Job Description: Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.