| **Navigation:**  [[advanced topics 1.htm|Advanced Topics]] > Multi Language Programming >====== Resolving Data Types ====== | [[compiler integration.htm|{{btn_prev_n.gif|Previous page}}]][[advanced topics 1.htm|{{btn_home_n.gif|Return to chapter overview}}]][[prototyping 3gl functions in clarion.htm|{{btn_next_n.gif|Next page}}]] | | || 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 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 Clarion by the assignment statement). The table below gives a brief cross reference of the parameters types supported by the Clarion, C++ and Modula-2 compilers; as detailed, some parameters require additional pragma statements to work correctly. The Clarion SIGNED and UNSIGNED data types are equates that change type from LONG and ULONG. | __**Clarion**__ | __**C++**__ | __**Modula-2**__ | | **BYTE** | **unsigned char** | **BOOLEAN** | | **BYTE** | **unsigned char** | **SHORTCARD** | | ***BYTE** | **unsigned char *** | **var SHORTCARD** | | **USHORT** | **unsigned short** | **CARDINAL** | | ***USHORT** | **unsigned short *** | **var CARDINAL** | | **SHORT** | **short** | **INTEGER** | | ***SHORT** | **short *** | **var INTEGER** | | **LONG** | **long** | **LONGINT** | | ***LONG** | **long *** | **var LONGINT** | | **ULONG** | **unsigned long** | **LONGCARD** | | ***ULONG** | **unsigned long *** | **var LONGCARD** | | **SREAL** | **float** | **REAL** | | ***SREAL** | **float *** | **var REAL** | | **REAL** | **double** | **LONGREAL** | | ***REAL** | **double *** | **var LONGREAL** | | **STRING** | **//can't pass by value//** | **//can't pass by value//** | | ***STRING** | **unsigned int, char *** | **CARDINAL, ARRAY OF CHAR** | | ***STRING(with RAW)** | **char[]** | **var ARRAY OF CHAR** | | ***CSTRING(with RAW)** | **char[] or char *** | **var ARRAY OF CHAR** | | ***PSTRING** | **char[] or Char *** | **ARRAY OF CHAR** | | **GROUP** | **struct** | **var record type** | | ***GROUP(with RAW)** | **struct *** | **var record type** | | ***?** | **void far*** | **FarADDRESS** | | **UNSIGNED** | **unsigned int** | | | **SIGNED** | **int** | | Clarion STRING variables are normally passed as two parameters: first, a UNSIGNED which contains the length of the data buffer; second, the address of the data. CSTRINGs and PSTRINGs are passed the same as STRINGs (as two parameters). The RAW attribute can be used in the Clarion prototype to pass only the address of the string data to external 3GL functions (Clarion language procedures do not need, or support, RAW). __**C and C++ Data Type Equivalents**__ The following data type equivalents can be 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 {** **        char *pucString; ** **        CLALONG 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 procedure. 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, char *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, an UNSIGNED 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. In practice there need not be any instances of Struct2 defined. **  Struct2         GROUP,TYPE        ! 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)** **      Struct4         LIKE(Struct2)** 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,TYPE          ! 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 code. **       CONST** **          BYTE    ::= BYTE;** **          SHORT   ::= INTEGER (16-bit);** **          USHORT  ::= CARDINAL (16-bit);** **          LONG    ::= LONGINT;** **          ULONG   ::= LONGCARD;** **          SREAL   ::= REAL;** **          REAL    ::= LONGREAL;** Clarion DATE and TIME data types may be passed to Modula-2 procedures 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, an UNSIGNED 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 can be 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 code. **        ALIAS** **          SHORT   = INT16;** **          USHORT  = INT16;** **          LONG    = INTEGER;** **          ULONG   = INTEGER;** **          SREAL   = SHORTREAL;** Clarion DATE and TIME data types may be passed to Pascal procedures 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 : ^CHAR;** **          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.**