User Tools

Site Tools


resolving_data_types.htm
Navigation:  Advanced Topics > Multi Language Programming >====== Resolving Data Types ====== Previous pageReturn to chapter overviewNext 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.**

resolving_data_types.htm.txt · Last modified: 2021/04/15 15:57 by 127.0.0.1