Board index » delphi » Linking C in Turbo Pascal or Borland Pascal?

Linking C in Turbo Pascal or Borland Pascal?

In <3A194797.CE4FA...@renault.fr>, Antoine Leca
<Antoine.L...@renault.fr> wrote

Quote
>Patrick D. Rockwell wrote:

>> 1. I know that you can write assembly language into a unit, but can you
>> put C code into it?

>Not directly: you should use the C compiler (funny, isn't it?)
>to create .obj, and then you can link the .obj the same way
>as independant assembler sources. Just take care of the '_'
>prepended to C names...

And a few other things as well:
1. Code segment must be called CODE or CSEG
2. Data segment must be called DSEG or DATA
3. No initialised STATICS - ie no initialised data in C source
4. All symbols must have legal pascal names
5. No GROUPS or CLASSES in the C source
6. Small memory model

You also need to enforce the Far Call {$F+} model when calling the
external C routine.

For 16bit TurboC compiler then you can create a TP/BP compatible
.obj if you use *all* of the following command-line options:
-wrvl    {enable all warnings}
-p       {use pascal calling conventions}
-k-      {standard stack frame off}
-r       {use the register variables - SI/DI become general purpose}
-u-      {underscore generation is off}
-c       {compile to .obj only}
-ms      {ensure small memory model}
-zCCODE  {name code segment CODE}
-zP      {do not create the code group}
-zA      {do not create the code class}
-zRCONST {name static data segment CONST}
-zS      {do not create the data group}
-zT      {do not create the data class}
-zDDATA  {name data segment DATA}
-zG      {do not create the BSS group}
-zB      {do not create the BB class}

There is one extra potential problem:

If you want to call a Pascal procedure from the C module then you need
to save and restore SI/DI in the C module before you make the call and
then restore them afterwards. A C macro in a header file will do nicely
plus a couple of extra lines in the Pascal program:

SAVESIDI.H

typedef unsigned int WORD;

#define save_sidi {extern WORD far *_rsp; *_rsp++ = _SI; *_rsp++ = _DI;}
#define rest_sidi {extern WORD far *_rsp; _DI = *--_rsp; _SI = *--_rsp;}

In the Pascal program you need to define

var _rsp : Pointer;
var SiDiStack : Array[0..10] of word;

& place the following line within the program before you call any
routine in the C module:

_rsp := @SiDiStack;

Quote

>HOWEVER, the C runtime library (malloc, printf) is not usable
>(because it is not linked in), so a fair amount of C code cannot
>be linked.

Only if you have the RTL source and recompile using the options above
then link in the RTL modules used as well. However, even with the RTL
source modified as above,  there are still linking problems - such as
the way C and Pascal handle constant strings.

--
Pedt

 

Re:Linking C in Turbo Pascal or Borland Pascal?


Quote
Pedt Scragg wrote:

> In <3A194797.CE4FA...@renault.fr>, Antoine Leca
> <Antoine.L...@renault.fr> wrote
> >Patrick D. Rockwell wrote:

> >> 1. I know that you can write assembly language into a unit, but can you
> >> put C code into it?

> >Not directly: you should use the C compiler (funny, isn't it?)
> >to create .obj, and then you can link the .obj the same way
> >as independant assembler sources. Just take care of the '_'
> >prepended to C names...

> And a few other things as well:

Certainly I was quick on this: this is nowhere from easy.
However some of the points you made are not that of a problem.

Quote
> 1. Code segment must be called CODE or CSEG

Well, TP6+ accept any segment whose name ends with _TEXT.
Sympathic.

Quote
> 2. Data segment must be called DSEG or DATA

Again, TP6+ improves here, and allows also _BSS.

Quote
> 3. No initialised STATICS - ie no initialised data in C source

Well (sorry Pedt, it was a big move!), TP6+ allows them,
in a segment whose name end with _DATA (not to be mixed with
the above, though).
I am unsure which versions allows for relocations inside
this segment, though.

Quote
> 4. All symbols must have legal pascal names

TP5.5+ adds the syntax "object_type@method_name", to denote
methods written in assembler. But this does not fit with C++.

OTOH, C (not C++) compilers will generate legal Pascal symbols,
except perhaps for three cases (which refers to the C RTL):
- use of 32-bit arithmetic
- use of far pointer arithmetic
- direct manipulation of struct
These cases have to be studied by compiler...

Quote
> 5. No GROUPS or CLASSES in the C source

Again, DGROUP is accepted and handled correctly in TP6+
Classes are ignored (perhaps in earlier compilers too).

The bottom line is that you better has to use TP6, TP7 or
Delphi if you really want to interface with C.
Sorry to not have made this clear on the first shot.

Quote
> 6. Small memory model

Ah! yes, this is for sure, you need to use the large model
(or you want to play, to force any interfaced pointers
to be far...)

Quote
> You also need to enforce the Far Call {$F+} model when calling the
> external C routine.

I am not sure this is required.
What is required is that the calling model for functions (near
or far) should agree with the status of the $F option.
In large and medium models, functions defaults to far {$F+}
In small and compact models, functions defaults to near {$F-}
Tiny and huge models won't work.

Quote
> For 16bit TurboC compiler then you can create a TP/BP compatible
> .obj if you use *all* of the following command-line options:

See Pedt's post for the -z* options, I believe he's correct,
except on the followings:

Quote
> -wrvl    {enable all warnings}

  -w do so instead (-wrvl enables "Function should return a
      value" warning only).
  -w-nak is a good idea, though, if you want to avoid noise...

Quote
> -k-      {standard stack frame off}

Why? it works with -k also.
Certainly, -N should *NOT* be used, OTOH.

Quote
> -r       {use the register variables - SI/DI become general purpose}

I prefer to drop registers, so to use -r-

Quote
> -u-      {underscore generation is off}

This is unnnecessary, the _pascal (-p) keyword removes the
underline on exported identifiers. This is also a nuisance if
you want to link with (part of) the C RTL later.

Quote
> -ms      {ensure small memory model}

This is not in line with the above discussion.

Quote
> There is one extra potential problem:

> If you want to call a Pascal procedure from the C module then you need
> to save and restore SI/DI in the C module before you make the call and
> then restore them afterwards.

This is not needed if you disable register optimisation (-r-),
which is a good option, unless you have a very big quantity of
C code to link in.

Quote
> >HOWEVER, the C runtime library (malloc, printf) is not usable
> >(because it is not linked in), so a fair amount of C code cannot
> >be linked.

> Only if you have the RTL source and recompile using the options above
> then link in the RTL modules used as well. However, even with the RTL
> source modified as above,  there are still linking problems - such as
> the way C and Pascal handle constant strings.

Also the C RTL functions for 32-bit, far pointers or struct's...
The most real nuisance, as I experienced (so I get better with MS-C).

Also you need to rewrite the malloc library to insert itself in
the TP model (this looks possible, but I did not do it.
I am interested if someone began such a project, by the way.)

For the upper form, you may consider rewrite <stdio.h> if you want to
share TP "File"'s and C "FILE"'s (again, not-an-easy job...)

Antoine

Re:Linking C in Turbo Pascal or Borland Pascal?


Im Artikel <3A1BFFC3.BCB4F...@renault.fr>, Antoine Leca
<Antoine.L...@renault.fr> schreibt:

Quote
>Please, be fair! Imagine you have a Turbo Pascal compiler that produces
>.obj (like Delphi 2+ does). Do you imagine that the resulting .obj
>will mix well with the C runtime library? It won't.

You're right, languages didn't mix well in former times. As soon as I/O or
memory management was required, the underlaying runtime system usually was
initialized only for the language of the main module, and calls from other
language modules would fail in their uninitialized language specific runtime
system.

But nowadays I often wonder, to what degree objects of different high level
languages can be linked into a working program. But that's not a merit of the
new compilers themselves, but instead of the compiler providers, which now tend
to use the same runtime system for all their compilers, or delegate all
difficult tasks to the operating system.

I.e. if you use the Borland C++ Builder, then you can freely combine Pascal and
C modules into the same project. This is true due to the fact, that BCB also
can compile Pascal units, and IMO shares the same runtime system with Delphi.
Using Delphi in contrast to BCB, to make a program, will require that all
non-Pascal units have been translated with BCB before.

Since I missed the begin of this thread, and also are not familiar with neither
TP nor BP, I'll leave most other questions uncommented. I'll only add a comment
about the passes, required by a compiler:

First we should distinguish between a "dumb" compiler, which only can compile
one module at a time, and a more sophisticated compiler, which can compile
multiple modules at the same time.

Then a "dumb" compiler will fail, if any referenced (used) module was not
previously compiled. In this case it's up to a Make utility, to determine which
modules must be compiled in what order, to make such dumb compilers work.

A "smart" compiler instead always uses (at least) 2 passes, where the first
pass covers the compilation of the exports (interface section) of every given
(or otherwise used) units, and the following passes cover the compilation of
the implementation of the units, based upon the previously compiled units. Here
a Pascal compiler usually is much faster than a C compiler, since in Pascal the
dependencies between the units are built into the language, whereas a C
compiler must compile the #included header files for every single module, over
and over again. The "precompiled header files" only are a workaround, to bypass
this deficiency of the C language.

The speed of a compiler should be weighted separately from the speed of the
final program. Since nowadays most compilers share the same code generator, the
speed of the executable code does not differ significantly amongst languages.
But the compiler itself can spend a very different amount of time with every
module, depending on the programming language of that module.

DoDi

Re:Linking C in Turbo Pascal or Borland Pascal?


Quote
In article <20001125023505.09052.00000...@nso-ck.aol.com>, VBDis wrote:
>Im Artikel <3A1BFFC3.BCB4F...@renault.fr>, Antoine Leca
><Antoine.L...@renault.fr> schreibt:

>The speed of a compiler should be weighted separately from the speed of the
>final program. Since nowadays most compilers share the same code generator,

Compilers from the same manufactorer, yes. But VC and BCB are different, and
so is GCC, Metroworks etc..

Same for Pascal: Delphi, the free pascal compilers, Metroworks, TP even.

Go to page: [1] [2]

Other Threads