Declaring the external object code

Linking to an object file

Having declared the external function or variable that resides in an object file, you can use it as if it was defined in your own program or unit. To produce an executable, you must still link the object file in. This can be done with the {$L file.o} directive.

This will cause the linker to link in the object file file.o. On most systems, this filename is case sensitive. The object file is first searched in the current directory, and then the directories specified by the -Fo command line.

You cannot specify libraries in this way, it is for object files only.

Here we present an example. Consider that you have some assembly routine which uses the C calling convention that calculates the nth Fibonacci number:

 .text
         .align 4
 .globl Fibonacci
         .type Fibonacci,@function
 Fibonacci:
         pushl %ebp
         movl %esp,%ebp
         movl 8(%ebp),%edx
         xorl %ecx,%ecx
         xorl %eax,%eax
         movl $1,%ebx
         incl %edx
 loop:
         decl %edx
         je endloop
         movl %ecx,%eax
         addl %ebx,%eax
         movl %ebx,%ecx
         movl %eax,%ebx
         jmp loop
 endloop:
         movl %ebp,%esp
         popl %ebp
         ret
Then you can call this function with the following Pascal Program:
 Program FibonacciDemo;
 
 var i : longint;
 
 Function Fibonacci (L : longint):longint;cdecl;external;
 
 {$L fib.o}
 
 begin
   For I:=1 to 40 do
     writeln ('Fib(',i,') : ',Fibonacci (i));
 end.
With just two commands, this can be made into a program:
 as -o fib.o fib.s
 ppc386 fibo.pp
This example supposes that you have your assembler routine in fib.s, and your Pascal program in fibo.pp.
Linking to a library

To link your program to a library, the procedure depends on how you declared the external procedure.

In case you used the following syntax to declare your procedure:

 Procedure ProcName (Args : TPRocArgs); external 'Name';
You don’t need to take additional steps to link your file in, the compiler will do all that is needed for you. On WINDOWS it will link to name.dll, on LINUX and most UNIX’es your program will be linked to library libname, which can be a static or dynamic library.

In case you used

 Procedure ProcName (Args : TPRocArgs); external;
You still need to explicity link to the library. This can be done in 2 ways:
  1. You can tell the compiler in the source file what library to link to using the {$LinkLib 'Name'} directive:
          {$LinkLib 'gpm'}
    
    This will link to the gpm library. On UNIX systems (such as LINUX), you must not specify the extension or ’lib’ prefix of the library. The compiler takes care of that. On other systems (such as WINDOWS, you need to specify the full name.
  2. You can also tell the compiler on the command-line to link in a library: The -k option can be used for that. For example
          ppc386 -k'-lgpm' myprog.pp
    
    Is equivalent to the above method, and tells the linker to link to the gpm library.

As an example; consider the following program:

 program printlength;
 
 {$linklib c} { Case sensitive }
 
 { Declaration for the standard C function strlen }
 Function strlen (P : pchar) : longint; cdecl;external;
 
 begin
   Writeln (strlen('Programming is easy !'));
 end.
This program can be compiled with:
 ppc386  prlen.pp
Supposing, of course, that the program source resides in prlen.pp.

To use functions in C that have a variable number of arguments, you must compile your unit or program in objfpc mode or Delphi mode, and use the Array of const argument, as in the following example:

 program testaocc;
 
 {$mode objfpc}
 
 Const
   P : Pchar
     = 'example';
   F : Pchar
     = 'This %s uses printf to print numbers (%d) and strings.'#10;
 
 procedure printf(fm: pchar;args: array of const);cdecl;external 'c';
 
 begin
  printf(F,[P,123]);
 end.
The output of this program looks like this:
 This example uses printf to print numbers (123) and strings.