            Interfacing C, C++, Pascal, or Modula-2 to Clarion 3.0
==============================================================================

This document is a guide to using C, C++, Pascal, or Modula-2 code and data
within Clarion 3.0 Applications.  

Clarion Database Developer v3.0 is an exceptional application development
tool.  In just a few hours it is possible to generate an application that
could take weeks or months to code from scratch using conventional programming
tools (such as C or C++).  Clarion 3.0 also has object code generation
capability that rivals that of many C compilers.  

So why use C, C++, Pascal, or Modula-2 code at all in a Clarion application? 
The answer is, most developers won't.  Most Clarion developers will probably
develop large, complex applications without ever having the need to link to
external routines written in another language.

However, there are a number of libraries available (for example: statistical,
financial, graphics, communications, and many more) which could significantly
cut the development time of an application which requires these capabilities. 
Most of these libraries are written in C.  However, many powerful C++, Pascal,
and Modula-2, libraries are also available.  This is the reason the capability
of interfacing Clarion to C, C++, Pascal, and Modula-2 is so important. 
Clarion 3.0 allows you to use these libraries in their "native" form without
"re-inventing the wheel."

The code examples in this document assume that you will use a TopSpeed
compiler (other compiler's requirements are also discussed).  Since Clarion
3.0 uses TopSpeed code generation and linking technology, it is easiest to
link code produced with TopSpeed Compilers to Clarion applications.  Clarion
3.0 does provide facilities to link code produced by other third party
compilers (like Microsoft C), however some care is required as well as a good
understanding of the operation of both compilers (see the Using External
Libraries essay in the Programmer's Guide).  It is not generally possible to
directly link C++ code produced by C++ compilers other than TopSpeed (the
reasons are explained later in this document).

Clarion Data Types
==================

The Clarion language defines the data types BYTE, SHORT, USHORT, LONG, ULONG,
SREAL, REAL, and STRING which map fairly easily to C, C++, Pascal, and Modula-
2 equivalents.  Clarion also defines DATE and TIME data types, and GROUP
structures, which may be mapped to structures in each language.  CSTRING and
PSTRING data types are specifically provided by Clarion to simplify
interfacing with external functions using C or Pascal conventions.

The DECIMAL, PDECIMAL, BFLOAT4, and BFLOAT8 types are not discussed in this
document because it is very unlikely that these types of variables will ever
be used in C, C++, Pascal, or Modula-2 code.  If data of any of these types
does need to be passed to C, C++, Pascal, or Modula-2 code, simply assign the
value to a REAL or SREAL variable and pass that to the function (data type
conversion is automatically handled in the assignment statement).

Clarion STRING variables are normally passed as two parameters: first, a
USHORT is passed which contains the length of the data buffer; second, the
address of the data.  CSTRINGs are passed in the same way, the only difference
is that the string is NULL terminated.  PSTRINGs are also passed in the same
way, with the first byte of the data buffer containing the number of
characters in the string.  The RAW attribute may be used in the Clarion
procedure prototype to pass only the address of the string data to external
functions (Clarion functions do not need, or support, RAW).


C and C++ Data Type Equivalents
===============================

The following data type equivalents are used with C or C++ code.  These
typedefs should appear in the .H header file referenced by the C or C++ code. 
The CLA prefix is used to avoid name clashes with third party libraries.

      typedef unsigned char   CLABYTE;
      typedef short           CLASHORT;
      typedef unsigned short  CLAUSHORT;
      typedef long            CLALONG;
      typedef unsigned long   CLAULONG;
      typedef float           CLASREAL;
      typedef double          CLAREAL;

Clarion DATE and TIME data types may be passed to C functions as a CLALONG,
the CLADATE and CLATIME unions can then be used to resolve the elements of the
date or time from the CLALONG value.

      typedef union {
          CLALONG         n;
          struct {
              CLABYTE     ucDay;
              CLABYTE     ucMonth;
              CLAUSHORT   usYear;
          }               s;
      }   CLADATE;

      typedef union {
          CLALONG         n;
          struct {
              CLABYTE     ucHund;
              CLABYTE     ucSecond;
              CLABYTE     ucMinute;
              CLABYTE     ucHour;
          }               s;
      }   CLATIME;

Because of Clarion's two parameter method of passing STRINGs, the CLASTRING
structure is useful for certain internal uses, but cannot be used to accept
parameters from Clarion:

      typedef struct {CLABYTE *pucString; CLAUSHORT usLen} CLASTRING;

Clarion  STRING variables are not NULL terminated, they are padded with spaces
up to the length of the data buffer.  The trailing spaces can be removed by
using the Clarion CLIP function.  The following code declares a STRING of 20
characters, assigns some data into it, and passes it as a parameter to a C or
C++ function.  

      StringVar    STRING(20)
        CODE
        StringVar = 'Hello World...'
        C_Write_Function(StringVar)

The C or C++ function might be defined as:

      extern void C_Write_Function(CLAUSHORT usLen, CLABYTE bData[]) 
      {   CLAUSHORT usNdx = 0;

          while (usNdx < usLen)
      #ifdef __cplusplus
              cout << bData[usNdx++];
      #else
              putchar(bData[usNdx++]);
      #endif
      }

In the above example, usLen would have a value of 20 and bData would be padded
with trailing spaces.  This padding would be written to the screen by
C_Write_Function().  Many C routines expect a string to be NULL terminated. 
To address this issue, Clarion provides the CSTRING data type.  CSTRING
variables are automatically NULL terminated when data is assigned to them. 
This makes it possible for existing C routines to operate on the data.

A Clarion GROUP may be declared to contain related data.  A group is roughly
equivalent to a C or C++ struct.  When passed as a parameter to a procedure,
GROUPs are normally passed as three parameters: first, a USHORT is passed
which contains the size of the GROUP; second, the address of the GROUP
structure; and third, the address of a buffer containing a type descriptor for
the GROUP.  The contents of the type descriptor are not discussed here and are
subject to change in future versions of Clarion.  GROUPs may be nested, and
other GROUPs may be defined to assume the same structure as a previously
declared GROUP.  There are several forms of declaration for Clarion GROUPs:

      Struct1         GROUP                 ! Struct1 is defined as a GROUP 
      ul1               ULONG               ! containing two ULONG values 
      ul2               ULONG
                      END

This form of definition reserves space for Struct1 and is equivalent to the C
definition:

      struct {
          CLAULONG    ul1;
          CLAULONG    ul2;
      }   Struct1;

In the following example, the declaration of Struct2 declares a GROUP similar 
to that defined by Struct1, however no space is reserved.  Instead it is
assumed that there may be some EXTERNAL data conforming to this structure.  In
practice there need not be any instances of Struct2 defined.

      Struct2         GROUP, EXTERNAL         ! Struct2 is declared as a GROUP
      ul3               ULONG                 ! containing two ULONG values
      ul4               ULONG
                      END

The corresponding C definition is:

      typedef struct {
          CLAULONG    ul3;
          CLAULONG    ul4;
      }   Struct2

In the following example, the definitions of Struct3 and Struct4 define them
to be LIKE(Struct2), i.e. of the same internal structure.  In order to
distinguish members of Struct3 and Struct4 from those of Struct2 the S3 and S4
prefixes must be used.  Struct3 and Struct4 define instances of Struct2 (which
is not necessarily defined anywhere).  In both cases space is reserved.

      Struct3         LIKE(Struct2), PRE(S3)
      Struct4         LIKE(Struct2), PRE(S4)

The corresponding C definitions are:

      typedef Struct2 Struct3;
      typedef Struct2 Struct4;

      Struct3     S3;
      Struct4     S4;

Clarion GROUP declarations may be nested, for example:

      Struct5         GROUP, EXTERNAL         ! Struct5 is defined as a GROUP
      Struct6           GROUP                 ! containing a nested GROUP 
      ul5                 ULONG
      ul6                 ULONG
                        END
                      END

The equivalent C declaration is:

      typedef struct {
          struct {
              CLAULONG    ul5;
              CLAULONG    ul6;
          }   Struct6;
      }   Struct5;


Modula-2 Data Type Equivalents
==============================

The following data type equivalents are used with Modula-2 code.  These
definitions should appear in the Modula-2 definition module referenced by the
Modula-2 code.  These should be used to define parameter and return types of
procedures that will be called from  Clarion 3.0 code.

       CONST
          BYTE    ::= BYTE;
          SHORT   ::= INTEGER;
          USHORT  ::= CARDINAL;
          LONG    ::= LONGINT;
          ULONG   ::= LONGCARD;
          SREAL   ::= REAL;
          REAL    ::= LONGREAL;

Clarion DATE and TIME data types may be passed to Modula-2 functions as a
LONG, the DATE and TIME RECORDs can then be used to resolve the elements of
the date or time from the LONG value.

          DATE = RECORD
            CASE : BOOLEAN OF
            | TRUE:
              l         : LONG;
            ELSE
              ucDay     : BYTE;
              ucMonth   : BYTE;
              usYear    : SHORT;
           END
          END;

          TIME = RECORD
            CASE : BOOLEAN OF
            | TRUE:
              l         : LONG;
            ELSE
              ucHund    : BYTE;
              ucSecond  : BYTE;
              ucMinute  : BYTE;
              ucHour    : BYTE;
            END
          END;

Clarion STRINGs are passed in the same manner as Modula-2 open ARRAY OF CHAR 
parameters with the call(o_a_copy=>off) pragma in effect (the length and  the
address of the string are passed).

The following example code declares a string of 20 characters, assigns some
data into it and passes it as a parameter to a Modula-2 procedure

            MAP
              MODULE('M2_Code')
                M2_Write_Proc(STRING), NAME('M2_Code$M2_Write_Proc')
              END
            END
      StringVar    STRING(20)
            CODE
            StringVar = 'Hello World...'
            M2_Write_Proc(StringVar)

The Modula-2 procedure  might be defined as:

      DEFINITION MODULE M2_Code;

      (*# save, call(o_a_copy=>off) *)
      PROCEDURE M2_Write_Proc(StringVar: ARRAY OF CHAR);
      (*# restore *)
      END M2_Code.

Note that Clarion STRINGs are not NULL terminated, they are padded with spaces 
up to the length of the data buffer.  In the above example, StringVar would be 
padded with spaces up to a length of 20 characters.  Variables of type CSTRING
are automatically NULL terminated when data is assigned to them.  This makes
it possible for existing Modula-2 routines to operate on the data.

A Clarion GROUP is roughly equivalent to a Modula-2 RECORD.  There are several
forms of declaration for Clarion GROUPs.  The following conforms to the
Modula-2 declaration of the DATE type above:

      DateType GROUP
      n          LONG
      d          GROUP, OVER(n)
      ucDay        BYTE
      ucMonth      BYTE
      usYear       SHORT
                 END
               END

The OVER attribute is used to ensure that n and d occupy the same memory, the
total size of the group is the size of the member n.  When passed as
parameters, GROUPs are normally passed as three parameters: first, a USHORT is
passed which contains the size of the GROUP; second, the address of the GROUP
structure, and third, the address of a buffer containing a type descriptor for
the GROUP.  The contents of the type descriptor are not discussed here and are
subject to change in future versions of Clarion.  You may use the RAW
attribute in your Clarion prototype for the Modula-2 procedure to instruct the
compiler to pass only the address of the GROUP, otherwise you must define your
Modula-2 procedure to take 2 extra parameters:

            MAP
              MODULE('M2_Code')
                M2_Proc1(*GROUP)
                M2_Proc2(*GROUP), RAW
              END
            END

The corresponding Modula-2 definition module would contain:

      DEFINITION MODULE M2_Code;

        TYPE
          GROUP = RECORD
            (* Members *)
          END;

        PROCEDURE M2_Proc1(Len: USHORT;  VAR Data: GROUP; TypeDesc: ADDRESS);
        PROCEDURE M2_Proc2(VAR Data: GROUP);
      END M2_Code.


Pascal Data Type Equivalents
============================

The following data type equivalents are used with Pascal code.  These should
be placed in the Pascal interface unit referenced by the Pascal code.  These
should be used to define parameter and return types of procedures that will be
called from Clarion 3.0 code.

        ALIAS
          SHORT   = INT16;
          USHORT  = INT16;
          LONG    = INTEGER;
          ULONG   = INTEGER;
          SREAL   = SHORTREAL;

Clarion DATE and TIME data types may be passed to Pascal functions as a LONG,
the DATE and TIME records can then be used to resolve the elements of the date
or time from the LONG value.

          DATE = RECORD
            CASE BOOLEAN OF
            TRUE:
              (n        : LONG);
            FALSE:
              (ucDay    : BYTE;
               ucMonth  : BYTE;
               usYear   : SHORT);
            END;

          TIME = RECORD
            CASE BOOLEAN OF
            TRUE:
              (n        : LONG);
            FALSE:
              (ucHund   : BYTE;
               ucSecond : BYTE;
               ucMinute : BYTE;
               ucHour   : BYTE);
            END;

Because of Clarion's two parameter method of passing STRINGs, the STRING
structure is useful for certain internal uses, but cannot be used to accept
parameters from Clarion:

        TYPE
          STRING = RECORD
            usLen     : USHORT;
            pucString : BYTE;
          END;

Clarion PSTRINGs are passed by address in the same manner as Pascal STRING
parameters with the call(s_copy=>off) pragma in effect (the length and the
address of the string are passed).

The following example code declares a string of 20 characters, assigns some
data into it and passes it as a parameter to a Pascal procedure

          MAP
            MODULE('Pas_Code')
              Pas_Write_Proc(*PSTRING), NAME('Pas_Code$Pas_Write_Proc')
            END
          END
      StringVar    PSTRING(20)
          CODE
          StringVar = 'Hello World...'
          Pas_Write_Proc(StringVar)

The Pascal procedure might be defined as:

      INTERFACE UNIT Pas_Code;

      (*# save, call(s_copy=>off) *)
      PROCEDURE Pas_Write_Proc(StringVar: STRING[HIGH]);
      (*# restore *)
      END.

A Clarion GROUP is roughly equivalent to a Pascal RECORD.  There are several
forms of declaration for Clarion GROUPs.  The following duplicates the Pascal
declaration of the DATE type above:

      DateType GROUP
      n          LONG
      d          GROUP, OVER(n)
      ucDay        BYTE
      ucMonth      BYTE
      usYear       SHORT
                 END
               END

The OVER attribute is used to ensure that n and d occupy the same memory, the
total size of the group is the size of the member n.  When passed as
parameters, GROUPs are normally passed as three parameters: first, a USHORT is
passed which contains the size of the GROUP; second, the address of the GROUP
structure; and third, the address of a buffer containing a type descriptor for
the GROUP.  The contents of the type descriptor are not discussed here and are
subject to change in future versions of Clarion.  You may use the RAW
attribute in your Clarion prototype for the Pascal procedure to instruct the
compiler to pass only the address of the GROUP, otherwise you must define your
Pascal procedure to take 2 extra parameters:

          MAP
            MODULE('Pas_Code')
              Pas_Proc1(*GROUP)
              Pas_Proc2(*GROUP), RAW
            END
          END

The corresponding Pascal interface unit might be:

      INTERFACE UNIT Pas_Code;

        TYPE
          GROUP = RECORD
            (* Members *)
          END;

        PROCEDURE Pas_Proc1(Len: USHORT;  VAR Data: GROUP; VAR TypeDesc);
        PROCEDURE Pas_Proc2(VAR Data: GROUP);
      END.


Resolving Different Naming Conventions
======================================

When linking code produced from different programming tools, it is essential
to ensure that the proper naming conventions are used.  If differing naming
conventions are used, the linker will not be able to resolve references to a
name within code (produced by one compiler) and its definition (within code
produced by another compiler).  In this case, no .EXE will be generated.  

Many C compilers (including TopSpeed) prepend an underscore to the name of
each function or variable name.  The Clarion NAME attribute simplifies
interfacing with code produced by these compilers by explicitly telling the
Clarion compiler the function or procedure name to generate for the linker. 
This allows you to explicitly code the Clarion prototype to follow the C
convention.  For example:

            MAP
              MODULE('My_C_Lib')
                StdStr_Parm(STRING), NAME('_StdStr_Parm')
              END
            END

When the Clarion compiler encounters the StdStr_Parm() procedure, it generates
the name _StdStr_Parm in the object code.  Although Clarion names are not case
sensitive, the name generated using the NAME attribute will appear exactly as
specified.

The following C language macro defines the Clarion naming conventions.  This
macro can be used when declaring C functions to interface with Clarion in
order to force the C compiler to generate names following the Clarion naming
convention (no prepended underscore and all upper case).

      #define CLA_CONV        name(prefix=>"", upper_case=>on)

C++ compilers encode the return and parameter types of a procedure into the
name that appears in the object code in a process known as 'name mangling'. 
Therefore, C++ compiled functions which may be called from Clarion 3.0 can be
declared within a 'extern "Pascal" {...};' modifier, which is the equivalent
to the C language CLA_CONV macro (which does not affect the name mangling
employed by the C++ compiler).  For example:

      extern "Pascal" void Clarion_Callable_Proc(void);

A more flexible form of the above, allowing for compilation by either a C or
C++ compiler, is:

      #ifdef __cplusplus
      extern "Pascal" {               /* Force Clarion conventions in C++ */ 
      #else
      #pragma save, CLA_CONV          /* Force Clarion conventions in C   */
      #endif

      void Clarion_Callable_Proc(void);   /* C or C++ declaration   */

      #ifdef __cplusplus
      }                               /* Restore C++ conventions     */
      #else
      #pragma restore                 /* Restore C conventions      */ 
      #endif

This form of declaration usually appears in a header file to be included by
any interface code.  It ensures that the correct conventions are used when
compiled with a C or C++ compiler and eliminates the need to use the NAME
attribute on the Clarion language prototype of the procedure or function.

Clarion is a case-insensitive language and the compiler converts the names of 
all procedures to upper-case.  Modula-2 and Pascal, however, are case
sensitive and also prefix the name of all procedure names with the name of the
module in the form: MyModule$MyProcedure.  The way to resolve these
differences is to use Clarion's NAME attribute to specify the full name of the
Modula-2 or Pascal procedure to the Clarion compiler:

            MAP
              MODULE('M2_Code')
                M2_Proc1(*GROUP), RAW, NAME('M2_Code$M2_Proc2')
              END
              MODULE('Pas_Code')
                Pas_Proc1(*GROUP), RAW, NAME('Pas_Code$Pas_Proc2')
              END
            END

The corresponding Modula-2 definition module might be:

      DEFINITION MODULE M2_Code;

        TYPE
          GROUP = RECORD
            (* Members *)
          END;
      
        PROCEDURE M2_Proc1(VAR Data: GROUP);
      END M2_Code.

The corresponding Pascal interface unit might be:

      INTERFACE UNIT Pas_Code;

        TYPE
          GROUP = RECORD
            (* Members *)
          END;
      
        PROCEDURE Pas_Proc1(VAR Data: GROUP);
      END.

The naming conventions used by Clarion 3.0 for data differ from those used for 
PROCEDURES and FUNCTIONS, and are more complex.  Therefore, the NAME()
attribute should be used to generate a Modula-2 or Pascal-compatible name for
any Clarion data that needs to be accessed between languages.  Modula-2 and
Pascal data names are case sensitive and prefixed with the name of the module
and a '@' in the form: MyModule@MyProc.


Resolving Different Parameter Passing Conventions
=================================================

Clarion 3.0 uses the TopSpeed object code generator, so it uses the same
efficient register-based parameter passing mechanism employed by all TopSpeed
languages.  If differing calling conventions are used by code compiled by
third-party compilers, the results may be unpredictable.  Typically, the
application will fail at run-time.

To use code produced by compilers other than TopSpeed, you must ensure that
either: 

      1) the other compiler generates code using Clarion's (TopSpeed's)
      parameter passing method, or, 

      2) that Clarion generates code using the other compiler's parameter
      method.  

You must also ensure that none of the functions return floating-point data
types.  There is no standard of compatibility between compilers regarding this
issue.  For example, Microsoft C returns floating-point values in a global
variable while Borland C returns them on the stack (TopSpeed also returns them
on the stack but there is no guarantee of compatibility).  Therefore, any
functions from non-TopSpeed compilers which must reference floating point
values and modify them should receive them "passed by address" and directly
modify the value -- do not have the function return the value.

Most other compilers don't provide Clarion-compatible parameter passing
conventions, but do provide standard C and Pascal parameter passing mechanisms
(passed on the stack).  Clarion 3.0 has the C and PASCAL procedure prototype
attributes to specify stack-based parameter passing.

Most non-TopSpeed C and C++ compilers use a calling convention where
parameters are pushed onto the stack from right to left (as read from the
parameter list).  The Clarion C attribute specifies this convention.  

Many C and C++ compilers also offer a Pascal calling convention where
parameters are pushed left to right from the parameter list.  This convention
is also utilized by most other languages on the PC.  The Clarion PASCAL
attribute generates calls using this convention.

In most cases, the C and PASCAL attributes are used in conjunction with  the
NAME attribute.  This is because many compilers prepend an underscore to
function names where the C convention is in use, and uppercase function names
where the PASCAL convention is in use (Clarion 3.0 uppercases procedure names
also).  For example:

            MAP
              MODULE('My_C_Lib')
                StdC_Conv(USHORT, ULONG), C, NAME('_StdC_Conv')
                StdPascal_Conv(USHORT, ULONG), PASCAL, NAME('STDPASCAL_CONV')
              END
            END

When the StdC_Conv procedure is called, the ULONG parameter is pushed on the
stack followed by the USHORT parameter.  When StdPascal_Conv is called, the
USHORT parameter is pushed followed by the ULONG parameter.  You should be
very careful that calling conventions match, otherwise the program may behave
unpredictably.  When interfacing with code produced by TopSpeed compilers, the
C and PASCAL calling convention attributes are not necessary because Clarion
3.0 uses the TopSpeed register-based calling conventions.

When writing TopSpeed C functions to be called from a Clarion program, the 
CLA_CONV macro (discussed above) should be used to select the correct naming
conventions.  The best way of achieving this is to declare any interface
functions in a separate header (.H) file and to apply the conventions to these
declarations.  C++ functions must be declared using "Pascal" external linkage
(also discussed above).  Modula-2 and Pascal naming conventions are best
handled by using the NAME attribute on the prototype.


Passing Parameters
==================

Clarion 3.0 offers two distinct methods of passing parameters to functions or
procedures: "passed by value" and "passed by address."

"Passed by value" means that the calling code passes a copy of the data to the
called  function or procedure.  The called code can then operate on the data
without affecting the caller's copy of the data.  These parameters are
specified by the parameter's data type in the prototype.

"Passed by address" means that the calling code passes the address of the data
to the called  function or procedure.  With this method, the called function
or procedure can modify the caller's data.  These parameters are specified by
prefixing the parameter's data type with an asterisk (*) in the prototype:

            MAP
              MODULE('My_C_Lib')
                Var_Parameter(*USHORT)          ! Parameter passed by address
                Val_Parameter(USHORT)           ! Parameter passed by value
              END
            END

These declarations represent the Clarion interface to the functions contained 
in the C library My_C_Lib.  The following example are the equivalent C
declarations:

      void    Var_Parameter(CLAUSHORT *uspVal);
      void    Val_Parameter(CLAUSHORT usVal);

Clarion parameters "passed by address" are equivalent to pointers to the
relevant C type.  Clarion "passed by value" parameters are passed in the same
way as C and C++ value parameters.

The corresponding Modula-2 definition module would be:

      DEFINITION MODULE M2_Code;

        IMPORT Cla;

        PROCEDURE Var_Parameter(VAR us: Cla.USHORT);
        PROCEDURE Val_Parameter(us: Cla.USHORT);
      END M2_Code.

The corresponding Pascal interface unit would be:

      INTERFACE UNIT Pas_Code;

        IMPORT Cla;

        PROCEDURE Var_Parameter(VAR us: Cla.USHORT);
        PROCEDURE Val_Parameter(us: Cla.USHORT);
      END.

When a Clarion STRING or GROUP is passed by value, a copy of the data is
created on the heap and this copy is passed to the called code.  When control
returns to the caller, the copy is destroyed.  This is a potential source of
problems when interfacing to C or C++ libraries which store STRING parameters
for later use, since the stored pointers will point to invalid data.  In
particular, if the data is later modified, the heap may become corrupted -
which can result in a system crash.  For this reason, it is safer to pass
STRINGs or GROUPs to C or C++ routines by address.


The EXTERNAL Attribute
======================

The EXTERNAL attribute is used to declare Clarion variables that are  defined
in an external library.  This provides Clarion programs with a means of
accessing public data in external libraries.  The compiler will not reserve 
space for any variables declared as EXTERNAL, making it possible to use 
EXTERNAL variable declarations for aggregate types similar to the typedef in
C.  For example:

      typedef struct {
          unsigned long   ul1;
          unsigned long   ul2;
          }   StructType;

      #ifdef __cplusplus
      extern "C" {     /* Use C naming conventions, which will require use */ 
      #endif           /* of the NAME attribute in the Clarion prototype   */

      StructType  Str1;         /* Define Str1                */ 
      StructType  Str2;         /* Define Str2                */

      #ifdef __cplusplus
      }                         /* Restore C++ conventions    */ 
      #endif

The following Clarion declarations are all that is necessary to make Str1 and 
Str2 available to Clarion programs.

      StructType  GROUP, EXTERNAL             ! Declare a user defined type 
      ul1           ULONG
      ul2           ULONG
                  END

      ! Declare Str1 and Str2 which are defined in the C module

      Str1        LIKE(StructType), PRE(S1), NAME('_Str1'), EXTERNAL 
      Str2        LIKE(StructType), PRE(S2), NAME('_Str2'), EXTERNAL

The NAME attribute is used to allow the linker to use the C naming convention
when referencing Str1 or Str2.


C++ Considerations
==================

There are some limitations which apply to  accessing C++ code and data from
Clarion 3.0.  C++ is an object oriented language and includes language
features to support classes and objects, polymorphism, operator and function
overloading, and class inheritance.  None of these features are supported in 
Clarion 3.0.  This does not prevent you from taking advantage of these
features in a Clarion and C++ application, but it does dictate the nature of
the interface code.

Clarion 3.0 is not object-oriented so it cannot directly access C++ classes,
or objects of a class type.  Therefore, Clarion programs do not have direct
access to the data or functions contained within those classes.  To access
them, it is necessary to provide a "C-like" interface to the C++
functionality.  A C style function can be called from Clarion, which would
then be able to access the C++ classes and objects defined within the code,
including their public data and methods.

The following example code fragment demonstrate how to code a C++ function
which calls a C++ class library.  The MakeFileList function may be called
directly from Clarion -- the DirList constructors and the ReOrder class member
may not.  The DirList class implements a directory list whose entries may be
ordered by name, size or date.  The class definition and Clarion callable
entry point declarations are as follows (note the use of the 'extern "C"'
linkage specifier to force C naming conventions for the Clarion callable
functions):

      //*** DirList Class Definition
      class DirList: public List {
      public:
          DirList(char *Path, CLAUSHORT Attr, CLAUSHORT Order);
          DirList();
          void ReOrder(int Order);
      };

      //*** Clarion Entrypoint Declarations
      extern "C" {
      void MakeFileList(char *Path, CLAUSHORT Attr, CLAUSHORT Order);
      }

The following code does nothing more than provide entry points for the  
Clarion code to access the functionality of the DIRLIST class library.   Since
Clarion performs no name-mangling and cannot access classes or their  members,
this API is necessarily fairly simple.

      DirList *FileList = NULL;              // The directory list object

      void MakeFileList(char *Path, CLAUSHORT Attr, CLAUSHORT Order) 
      {   if (FileList != NULL)              // If we have a list    
        {   delete FileList;                 // invoke class destructor
            FileList = NULL;                 // so we can start again
        }
        FileList = new DirList(Path, Attr, Order);
      }

The following is the corresponding MAP structure prototype to allow Clarion to
call the MakeFileList interface function:

          MAP
            MODULE('DirList')
              MakeFileList(*CSTRING,USHORT,USHORT),RAW,NAME('_MakeFileList')
            END
          END

One disadvantage of this is that, given a large class library, it appears to
involve a lot of extra work to create a suitable interface.  In practice,
however, it should only be necessary to provide a very small interface to
begin taking advantage of an existing C++ class library.

It is not possible to call C++ code compiled using non-TopSpeed C++ compilers
from a Clarion application.  C++ modules usually require special
initialization -- constructors for all static objects must be invoked in the
correct order.  This initialization process must be performed by the Clarion
3.0 start-up code.  Clarion's startup code automatically performs the
necessary initialization for any TopSpeed C++ modules that are present, but it
will not initialize modules compiled with other C++ compilers.  Even if the
modules did not require initialization, other C++ compilers use different
calling and naming conventions, and adopt different internal class structures. 
This makes it impossible to use C++ class libraries in Clarion applications
compiled with a compiler other than TopSpeed C++.


Modula-2 and Pascal Module Initialization
=========================================

Many Modula-2 and Pascal modules contain an initialization section which is
executed prior to executing the main program module.  If you are calling
Modula-2 or Pascal procedures in modules that require initialization, it is
essential to ensure that each module is initialized prior to use.  

The InitModules Clarion language procedure is provided to facilitate Modula-2
and Pascal module initialization.  The Clarion interface for the InitModules
procedure contains a full description of its use:

      !*** Modula-2 RTL Initialization Records
      _FIO        BYTE, DIM(0), EXTERNAL, NAME('FIO$')
      _FloatExc   BYTE, DIM(0), EXTERNAL, NAME('FloatExc$')
      _ShtHeap    BYTE, DIM(0), EXTERNAL, NAME('ShtHeap$')
      _Str        BYTE, DIM(0), EXTERNAL, NAME('Str$')
      _BiosIO     BYTE, DIM(0), EXTERNAL, NAME('BiosIO$')
      _FIOR       BYTE, DIM(0), EXTERNAL, NAME('FIOR$')
      _FormIO     BYTE, DIM(0), EXTERNAL, NAME('FormIO$')
      _Graph      BYTE, DIM(0), EXTERNAL, NAME('Graph$')
      _LIM        BYTE, DIM(0), EXTERNAL, NAME('LIM$')
      _MATHLIB    BYTE, DIM(0), EXTERNAL, NAME('MATHLIB$')
      _MsMouse    BYTE, DIM(0), EXTERNAL, NAME('MsMouse$')
      _IO         BYTE, DIM(0), EXTERNAL, NAME('IO$')
      _Lib        BYTE, DIM(0), EXTERNAL, NAME('Lib$')
      _SYSTEM     BYTE, DIM(0), EXTERNAL, NAME('SYSTEM$')
      _Storage    BYTE, DIM(0), EXTERNAL, NAME('Storage$')
      _Window     BYTE, DIM(0), EXTERNAL, NAME('Window$')
      
      !*** Pascal RTL Initialization Records
      _PasLib     BYTE, DIM(0), EXTERNAL, NAME('PasLib$')
      _PasDos     BYTE, DIM(0), EXTERNAL, NAME('PasDos$')
      _PasRed     BYTE, DIM(0), EXTERNAL, NAME('PasRed$')
      _PasProc    BYTE, DIM(0), EXTERNAL, NAME('PasProc$')
      
          MAP
            MODULE('InitMod')
              InitModules(LONG, LONG, <LONG>, <LONG>, <LONG>, <LONG>), |       
                 C, RAW, NAME('_InitModules');
            END
          END

InitModules must be the first call from the main program module of any Clarion
program that uses Modula-2 or Pascal modules that have initialization code. 
Up to 5 modules may be initialized with each call.  The last parameter passed
in the list must be a 0 (if 5 are passed, 0 is the 6th parameter; if 2 are
passed, 0 is the 3rd; etc.).  The parameters are the addresses of the
initialization records.

The declarations above the MAP are the initialization records for the Modula-2
and Pascal run-time libraries.  You must declare a similar initialization
record for any Pascal or Modula-2 modules you write.  The name of the
initialization record that appears in the NAME() attribute is the name of the
module with a '$' affixed:

      MyModule    BYTE, DIM(0), EXTERNAL, NAME('MyModule$') 
        CODE
        InitModules(MyModule, 0)


Summary
=======

Clarion Database Developer v3.0 provides a number of features to assist 
developers who need to interface to code written in other programming
languages.  With a little care, it  is possible to create Clarion 3.0
interfaces to some extremely powerful external libraries.  

There is a complete example included with this document which includes code
written in TopSpeed C, C++, Pascal, and Modula-2.  This example code
implements all the concepts discussed in this document.  This is your resource
which will "pull it all together" for you.

When preparing interfaces to libraries written in other languages you should
consider the following suggestions:

*     Don't write C, C++, Pascal, or Modula-2 functions to return CSTRING
      variables to Clarion.  Have the other language routine place the CSTRING
      value in a public variable, or pass a *CSTRING (by address) parameter to
      the C routine to receive the value.

*     Don't call Clarion functions which return STRING variables from other
      language functions.  Have the Clarion procedure place the return value
      in a public variable or pass a *CSTRING (by address) parameter to the
      other language procedure.

*     For simplicity and efficiency, STRING and GROUP parameters should
      usually be passed by address with the RAW attribute to ensure only the
      address is passed.

*     Test the application in XLARGE memory model first.


C and C++ Considerations
========================

*     If a C or C++ function takes a pointer parameter, the corresponding   
      parameter in the Clarion prototype for that function should be declared
      as "passed by address" by prefixing the data type with an asterisk (*).

*     If a C or C++ function takes a pointer to a GROUP, STRING, PSTRING or
      CSTRING, you should use the RAW attribute in the Clarion prototype.

*     If a C or C++ function takes an ASCIIZ string as a parameter, the
      corresponding parameter in the Clarion prototype should be *CSTRING.

*     If a C or C++ function takes a pointer to a structure as a parameter,
      the corresponding parameter in the Clarion prototype should be *GROUP.

*     Use the header (.H) files as a template for developing a Clarion
      interface to a C or C++ library which eliminates the need to use the
      NAME attribute on the Clarion prototype to specify names.

*     Use the NAME attribute on the Clarion prototype to specify names for C
      library functions which do not use the CLA_CONV macro - remember that C
      names are case sensitive and start with an underscore (_).


Modula-2 and Pascal Considerations
==================================

*     If a Modula-2 or Pascal function takes a VAR parameter, the
      corresponding parameter in the Clarion prototype for that function
      should be declared as "passed by address" by prefixing the data type
      with an asterisk (*).

*     If a Modula-2 or Pascal function takes a VAR parameter for a GROUP,
      STRING, PSTRING or CSTRING, you should use the RAW attribute in the
      Clarion prototype.

*     If a Modula-2 or Pascal function takes a VAR record as a parameter, the
      corresponding parameter in the Clarion prototype should be *GROUP and
      the RAW attribute should be used in the prototype.


Additional C++ Considerations
=============================

*     Use the "Pascal" external linkage specification for your C++ interface
      functions.  This eliminates the need to use the Clarion NAME attribute
      on the prototype.

*     Don't call C++ class member functions from your Clarion code.

*     Don't try to access C++ objects of class type from your Clarion code.

*     Don't try to access C++ code compiled with a C++ compiler other than
      TopSpeed.



Additional Modula-2 Considerations
==================================

*     Use the definition (.DEF) module as a template for developing a Clarion
      interface to a Modula-2 library.

*     If a Modula-2 function takes an ASCIIZ string as a parameter, the
      corresponding parameter in the Clarion prototype should be *CSTRING.

*     Use the NAME attribute to specify names for Modula-2 library functions -
      remember that Modula-2 names are prefixed with the module name followed
      by a '$' and are case-sensitive.


Additional Pascal Considerations
================================

*     Use the interface (.ITF) files as a template for developing a Clarion
      interface to a Pascal library.

*     Use the NAME attribute to specify names for Pascal library functions -
      remember that Pascal names are prefixed with the module name followed by
      a '$' and are upper-case.


