On portable C programming (was: libraw1394 struct layouts...)
Jim Kuzdrall
gnhlug at intrel.com
Thu Jan 8 08:20:12 EST 2009
On Thursday 08 January 2009 00:06, Ben Scott wrote:
> On Wed, Jan 7, 2009 at 11:31 PM, <VirginSnow at vfemail.net> wrote:
> > So what's the recommended way to do this?
>
> I dunno that there really is any really good way.
There is a solution to the problem, I believe, if the structs are
data structures that you wish to be common to several environments and
processors.
The problem is, as pointed out, that numeric values must be on
certain byte boundaries for different processors. Mixed in text does
not, but it will end up on a boundary if it follows a number (float,
double, integer, etc.). Any mixed-in text requires padding that varies
with the processor or compiler when the next number is reached.
The solution starts with a program for which the structs are
working. These structs are then read, one element at a time, by a
program that converts them to a "universal" format, creating a
universal struct. These functions are readily compiled on any system
without any adjustments, as it turns out.
Once created, the structs go into a "universal" struct library which
can be used various ways, depending on your needs. Your programs must
explicitely access all structs via a pointer array, constructed each
time the program loads. The program which uses the struct first
translates the universal struct to its native format. Then it replaces
the pointer the compiler put in the array with the location of the
translated struct.
You can allow all systems to access the struct library with the
universal format functions to keep the structs up to date. Or, if the
values are static, just translate the universal struct library to
several native libraries, which can be loaded in binary to their
respective programs.
So, what about these universal programs? The problem is the numeric
values. A crude solution would create the universal struct entirely of
ASCII by using printf(), strtol(), strtod(), etc. (Don't use scanf();
it usually causes more problems than is solves.)
A more elegant way was published in the "C/C++ Users Journal"
January 1995, page 33, entitled "Transferring Numeric Values Between
Computers" by (guess who) James A. Kuzdrall. P. J. Plauger was editior
and was enthralled by the universality of the technique. Neither the
numeric format of the host or the target computer need be known -
bigendian/littleendian, 32bit/64bit, 2,s compliment/BCD, none of that
changes the source code of the translation programs.
The functions are fputi, fgeti, fputl, fgetl, fputf, fgetf. fgetf
translates to and from a float of 32-bits, which can be cast to native
precision before storing in the native system. If you need more float
precision than 32-bits, the algorithm must be extended to double.
If anyone is interested, I will see if I can find my copy of the
article in text format and the source code for the functions. You must
be pretty conversant with numeric structures to follow the reasoning,
but using the functions is easy.
Jim Kuzdrall
P.S. If anyone wants this numeric transfer technique as this month's
topic for MerriLUG, let me know before noon today, 08 Jan, when the
notice goes out.
More information about the gnhlug-discuss
mailing list