[comp.sys.ibm.pc.programmer] Using Turbo C with libraries compiled with Microsoft C

johnson@cs.purdue.EDU (Bret Johnson) (06/04/90)

I am considering buying Turbo C++, but I need to link to a library
that is compiled with Microsoft C.  Specifically, I need to link
to the C interface library packaged with the KnowledgeMan database
system.  (This library is called TBL; it used to be called KC.)
As I understand, Turbo C, and thus I assume Turbo C++, sometimes
works with libraries compiled with Microsoft C and sometimes does't.
Could anyone please report their experiences using Turbo C with
libraries compiled with Microsoft C.  Are there any rules as to
when things work and when they don't?  Thank you.

				Bret Johnson
				johnson@cs.purdue.edu

tjr@cbnewsc.att.com (thomas.j.roberts) (06/05/90)

There are several (many ?) differences between Turbo C and Microsoft C.
Some of them are harmless, some will kill your program; some will kill
MS-DOS, some might even trash your disk(s).

THIS IS PROBABLY NOT A COMPLETE LIST!

1)	TC returns 4-byte results in AX/DX; MC uses AX/BX (float/double
	are returned in 8087 Top-Of-Stack register). This will make any
	large-pointer function misbehave dangerously, and will give
	erroneous results from any long function.
2)	TC and MC use different names for the various segments.
	This will probably prevent it from linking properly (except for
	huge model programs), and will cause subtle errors in a
	huge-model program.
3)	TC and MC package library routines differently, so you cannot
	use both the MC and the TC run-time libraries. If the third-party
	library depends upon the MC run-time library, this may cause
	link and/or run-time problems.
4)	TC and MC have different requirements for subroutines to preserve
	register contents. This will cause a serious disaster during
	execution (write-protect those disks before executing!).
5)	The TC run-time library screws around with the console hardware
	(even if you don't call any of its TEXT or GRAPHICS routines);
	this can often be minimized by setting directvideo=0.

In most cases, even if you manage to get the linker to link the program
and libraries without error, it will still die a horrible death when
executed (usually taking MS-DOS down, too).

In short, I strongly advise against trying to mix compilers in the same
program. If you simply cannot afford to buy the other compiler, then
you probably can make it work with the following kludges:

	1)	use TC huge model, and MC large model.
	2)	wrap every MC library routine with a special assembly
		routine to satisfy BOTH TC and MC register conventions
		(MC routine calling MC routine is probably OK as is).
		This special routine will need to manage DS.

Good luck [you will really need it!].

Tom Roberts
att!ihlpl!tjrob

mcdonald@aries.scs.uiuc.edu (Doug McDonald) (06/05/90)

In article <1990Jun4.205834.13661@cbnewsc.att.com> tjr@cbnewsc.att.com (thomas.j.roberts) writes:
>There are several (many ?) differences between Turbo C and Microsoft C.
>
>1)	TC returns 4-byte results in AX/DX;
This I have no idea about.

> MC uses AX/BX 
WRONG!!! Microscoft C uses AX/DX


Doug McDonald

dhinds@portia.Stanford.EDU (David Hinds) (06/06/90)

In article <1990Jun4.205834.13661@cbnewsc.att.com> tjr@cbnewsc.att.com (thomas.j.roberts) writes:
>There are several (many ?) differences between Turbo C and Microsoft C.
>Some of them are harmless, some will kill your program; some will kill
>MS-DOS, some might even trash your disk(s).
>
>2)	TC and MC use different names for the various segments.
>3)	TC and MC package library routines differently.
>4)	TC and MC have different requirements for subroutines to preserve
>	register contents. 
>5)	The TC run-time library screws around with the console hardware
>
>In short, I strongly advise against trying to mix compilers in the same
>program. If you simply cannot afford to buy the other compiler, then
>you probably can make it work with the following kludges...
>
    This sounds like an appropriate place to mention some of the benefits
of the Topspeed C compiler vs. Microsoft or Turbo C.  The topspeed compiler
allows you to specify just about anything having to do with calling
conventions on the fly - segment names, parameter passing in registers,
stack frame layout, inline function expansion, and register preservation.
And you can recompile the run-time libraries to use whatever calling
conventions you like.  So, you can generally use most 3rd party libraries, 
regardless of what compiler they were generated with, if you know its
calling conventions.  You just add some compiler directives to the header
files.

 -David Hinds
  dhinds@popserver.stanford.edu

bmarsh@cod.NOSC.MIL (William C. Marsh) (06/06/90)

Just thought I'd correct a few things, but mostly Tom's comments are
correct:

In article <1990Jun4.205834.13661@cbnewsc.att.com> tjr@cbnewsc.att.com (thomas.j.roberts) writes:
>1)	TC returns 4-byte results in AX/DX; MC uses AX/BX (float/double
>	are returned in 8087 Top-Of-Stack register). 

Wrong.  Both use DX:AX for longs, far pointers, etc.  I don't know about 
floats.

>4)	TC and MC have different requirements for subroutines to preserve
>	register contents. This will cause a serious disaster during

Both have requirements to save BP, SI, and DI (and DS!).  All others are
fair game for both compilers.

>5)	The TC run-time library screws around with the console hardware
>	(even if you don't call any of its TEXT or GRAPHICS routines);
>	this can often be minimized by setting directvideo=0.

Shouldn't matter to a third party routine, since Microsoft doesn't mess
about with the hardware, and the library would have to deal with it
anyway.

>In most cases, even if you manage to get the linker to link the program
>and libraries without error, it will still die a horrible death when
>executed (usually taking MS-DOS down, too).

Probably.  It's probably the segments (and groups) that are going to kill
you, also with internal functions (like long variable manipulation stuff)
that would be called in the third party library which are not in the TC
library.

Bill
-- 
Bill Marsh, Naval Ocean Systems Center, San Diego, CA
{arpa,mil}net: bmarsh@cod.nosc.mil
uucp: {ihnp4,akgua,decvax,dcdwest,ucbvax}!sdcsvax!nosc!bmarsh
"If everything seems to be coming your way, you're probably in the wrong lane."

bright@Data-IO.COM (Walter Bright) (06/06/90)

In article <1990Jun5.134159.9577@ux1.cso.uiuc.edu> mcdonald@aries.scs.uiuc.edu (Doug McDonald) writes:
<In article <1990Jun4.205834.13661@cbnewsc.att.com> tjr@cbnewsc.att.com (thomas.j.roberts) writes:
<<There are several (many ?) differences between Turbo C and Microsoft C.
<<1)	TC returns 4-byte results in AX/DX;
<This I have no idea about.
<< MC uses AX/BX 
<WRONG!!! Microscoft C uses AX/DX

Zortech also uses AX/DX. In fact, Zortech follows exactly MSC's segment
conventions, register saved/destroyed conventions, return value conventions
(including struct returns), Pascal conventions, etc. The only difference
is in floating point returns, ZTC's is different in order to make it
reentrant.

This is not enough, however, to make a 3rd party MSC library work with ZTC.
Trouble areas are:
1.	Using floating point.
2.	Depending on 'compiler helper' functions in the rtl, like long divide.
3.	Depending on the exact size and layout of the _iob[] struct in
	stdio.h (they're different between most compilers). This can cause
	very subtle crashes.
4.	Using undocumented internal MSC library functions.
5.	Depending on non-standard behavior of library functions (like
	strange things in printf format strings).

This is not to say it's impossible. For example, ZTC programs can use
the Microsoft Windows SDK libraries and the OS/2 PM libraries. This
works because I made it work. It's just that you can't casually do this.

Sometimes, people try and make things work by linking in *both* the MSC
runtime libraries and the ZTC runtime libraries. This is nearly always
doomed to failure, the usual result is lots of multiply-defined symbols
from the linker. Even if it linked successfully, just imagine what would
happen when you get some modules thinking _iob[] has one layout talking
to other modules thinking something else... not a pretty thing to do
to your hard disk!

In other words, the most practical courses of action are:
1. Only buy libraries that come with source, and recompile it for the
   compiler you're using.
2. Call the library vendor and request a version for the compiler you're
   using.

david@csource.OZ.AU (david nugent) (06/06/90)

In article <1990Jun4.205834.13661@cbnewsc.att.com>, tjr@cbnewsc.att.com (thomas.j.roberts) writes:

> 1) TC returns 4-byte results in AX/DX; MC uses AX/BX (float/double
> 	are returned in 8087 Top-Of-Stack register). This will make any
> 	large-pointer function misbehave dangerously, and will give
> 	erroneous results from any long function.

This is not the case.  Both compilers return long/large pointers in DX:AX


> 2) TC and MC use different names for the various segments.
> 	This will probably prevent it from linking properly (except for
> 	huge model programs), and will cause subtle errors in a
> 	huge-model program.

Since TC 1.5, Borland have been using identical segment naming conventions
to Microsoft.  Besides, they can be changed in TC to suit.


> 3) TC and MC package library routines differently, so you cannot
> 	use both the MC and the TC run-time libraries. If the third-party
> 	library depends upon the MC run-time library, this may cause
> 	link and/or run-time problems.

By and large, they are similar.  The problem really arises in the "help
functions" used by the compiler for, say long division, multiplication
and shifting.  They are named and called differently and each library
compiled with it's own compiler will of course use only it's version.


> 4)	TC and MC have different requirements for subroutines to preserve
> 	register contents. This will cause a serious disaster during
> 	execution (write-protect those disks before executing!).

Not at all true.  Both compilers require preservation of _only_ DS, SI,
DI and BP.


> 5) The TC run-time library screws around with the console hardware
> 	(even if you don't call any of its TEXT or GRAPHICS routines);
> 	this can often be minimized by setting directvideo=0.

Which has little to do with the compatibility between compilers...


david

-- 
  Unique Computing Pty Ltd, Melbourne, Aust.
  david@csource.oz.au  3:632/348@fidonet  28:4100/1@signet

bmarsh@cod.NOSC.MIL (William C. Marsh) (06/07/90)

In article <8@csource.OZ.AU> david@csource.OZ.AU (david nugent) writes:
>Since TC 1.5, Borland have been using identical segment naming conventions
>to Microsoft.  Besides, they can be changed in TC to suit.

However, if you change the names, you then have problems linking in the
default library.  Large model may get around this, but for smaller jobs
it would be a big problem...

Bill
-- 
Bill Marsh, Naval Ocean Systems Center, San Diego, CA
{arpa,mil}net: bmarsh@cod.nosc.mil
uucp: {ihnp4,akgua,decvax,dcdwest,ucbvax}!sdcsvax!nosc!bmarsh
"If everything seems to be coming your way, you're probably in the wrong lane."

joe@proto.COM (Joe Huffman) (06/08/90)

In article <2533@dataio.Data-IO.COM>, bright@Data-IO.COM (Walter Bright) writes:
> In article <1990Jun5.134159.9577@ux1.cso.uiuc.edu> mcdonald@aries.scs.uiuc.edu (Doug McDonald) writes:
> <In article <1990Jun4.205834.13661@cbnewsc.att.com> tjr@cbnewsc.att.com (thomas.j.roberts) writes:
> <<There are several (many ?) differences between Turbo C and Microsoft C.
.
.
.
> In other words, the most practical courses of action are:
> 1. Only buy libraries that come with source, and recompile it for the
>    compiler you're using.
> 2. Call the library vendor and request a version for the compiler you're
>    using.

One thing that I expected Walter to say but didn't, is that it is
possible for library vendors to supply a single library that will work 
across MSC, TC, and Zortech C/C++.  This is not possible in all cases, but in
many it is.  Walter had suggested I do this (and provided considerable help)
with the graphics library that is shipped with Zortech C/C++ (we have since
removed this feature, it now only works with Zortech).  It is also
possible to make this single library work with all memory models.

The basics of the procedure for doing this is:

1) Use patchobj (from Zortech) on all .OBJ modules to remove references to 
the memory model the library was compiled under and default library searches.

2) Declare all functions and pointers as 'far'.  Compile the library in
"Large" memory model.

3) Provide all your own low level functions.  Have NO unresolved externals
from your library (use libunres supplied by Zortech to find them).
This is a subtle problem, because the compiler generates function calls for 
things you didn't explicitly call, like long arithmetic.  I achieved this
by compiling my library with Zortech C and includeing the run time long
arithemetic module (with the functions renamed) in my library.  Use  
patchobj to rename all the long arithmetic functions to the new names. 

Hints, warnings, etc:

In the FG graphics library I had to supply a few odds and ends functions
like strcpy() and strcmp(), etc.  These were either made static or given
a new name (like fg_strcmp()).  If I had needed file I/O I would have had to
go directly to DOS and bypass the standard runtime library.  The math
library (sin(), pow(), etc) would be a major code size hit if it had been
necessary to duplicate them.  Fortunately my application didn't need this.  
Another major thing to watch out for is memory allocation.  Do you need 
malloc() and siblings?  Walter built in support for special versions in the 
runtime libraries for this, but it wouldn't be difficult for third party 
vendors to have their users supply the hooks for this.

I explain this with the hope that more third party vendors to support more 
compilers (especially Zortech of course).  It wasn't really that hard, and
all the strange stuff (patchobj) is handled in the makefile once it is 
figured out.

-- 
joe@proto.com
uunet!proto!joe
FAX: 208-263-8772