Retro video games delivered to your door every month!
Click above to get retro games delivered to your door ever month!
X-Hacker.org- The Library for Clipper - <b>introduction to c functions</b> http://www.X-Hacker.org [<<Previous Entry] [^^Up^^] [Next Entry>>] [Menu] [About The Guide]
                  INTRODUCTION TO C FUNCTIONS


     The Clipper Extend System allows the user access to functions
     written in other languages including C.  Chapter 11 of the
     Clipper Manual describes the use of the Extend System and it is
     recommended that the programmer reads this before including C
     routines in programs.  The ability to incorporate C functions in
     Clipper code greatly enhances the power of programs.  Not only
     can Clipper programmers take advantage of the routines available
     in .The Library. they can write their own.  The documented source
     code included with .The Library. provides useful models.

     A number of things should be borne in mind when writing C
     routines which can be called from Clipper.


     Parameter Checking

     The header file EXTEND.H must be included in your C routine since
     it contains the macros which allow you to take advantage of the
     parameter checking functions which are part of the Clipper
     library.


     There follows a list of macros from EXTEND.H.

     MACRO          Usage in parameter checking


     PCOUNT         checks number of parameters passed

     ISCHAR(n)      checks nth parameter is of type character

     ISNUM(n)       checks nth parameter is of type numeric

     ISLOG(n)       checks nth parameter is of type logical

     ISDATE(n)      checks nth parameter is of type date

     ISMEMO(n)      checks nth parameter is of type memo

     ISBYREF(n)     checks if nth parameter passed by reference

     ISARRAY(n)     checks nth parameter is of type array

     ALENGTH        checks length of array


     These functions are used to check that the correct amount of
     parameters have been passed and that they are all of the
     appropriate data type.

     If any parameter is found to be not of the correct type then an
     error message should be returned to the calling program.

     For example in the following code fragment checks are made to
     ensure that exactly three parameters are passed, that the first
     parameter is of type numeric the second is of type character and
     the third is an array.


          /*L_SAMPLE.C*/
          /*sample code to demonstrate parameter checking*/

          #include "planet.h"/*include Planet and Clipper headers*/
          #include "nandef.h"
          #include "extend.h"

          PLANET L_SAMPLE()   /* declare function */
          {
            if(PCOUNT==3 && ISNUM(1) && ISCHAR(2) && ISARRAY(3))
              {
              /* body of code to be executed if */
              /* parameters are in order */
              }
           else
              {
              _retc(ERR_SYNTAX);
              return;
              }
          }


     It should be noted that the number of variables to be passed to a
     particular function need not be fixed as in the above example.
     For example, the parameters could be passed in the form of an
     array and type checking done on each member of the array as it
     was used.


     Error Messages

     When a C function is called from Clipper and a numeric value is
     expected to be returned it is useful to return an error message
     which is a character expression thus making it easier for the
     Clipper program to detect that an error has been made.
     Obversely, when a character expression is expected a numeric
     error message should be returned.


     Parameter Passing

     The Extend System provides a number of C functions for receiving
     parameters from Clipper.


     FUNCTION    PASSES

     _parc()     passes a pointer to a Clipper character string

     _pards()    passes a character pointer to a Clipper date

     _parl()     passes a Clipper logical as an integer

     _parni()    passes a Clipper numeric as an integer

     _parnl()    passes a Clipper numeric as a long integer

     _parnd()    passes a Clipper numeric as a double


     Other functions with which a C function can receive information
     from Clipper are as follows:

     FUNCTION       PASSES

     _parclen()     passes length of character string

     _parcsiz()     passes the number of bytes in memory allocated for
                    the specified string including the null terminator.

     _parinfa()     passes type of an array element

     _parinfo()     tests the type of a passed parameter


          /*L_SAMPLE.C*/
          /*sample code to demonstrate parameter checking and passing*/

          #include "planet.h"/*include Planet and Clipper headers*/
          #include "nandef.h"
          #include "extend.h"

          PLANET L_SAMPLE()   /* declare function */
          {
            if(PCOUNT==3 && ISNUM(1) && ISCHAR(2)
               && ISARRAY(3))
              {
              double sum = 0;           /* declare and init vars */
              int num = _parni(1);      /* set num equal to parameter 1 */
              int length = _parclen(2); /* set strlen = length of
              param 2 */

              for (i=1; i<=ALENGTH(3); i++) /* for each element of param 3 */
               if(_parinfa(3,i) == NUMERIC) /* if element is a number */
                  sum += _parnd(3,i);       /* add the element of */
                                            /* array to sum */
              }
          else
              {
              _retc(ERR_SYNTAX);
              return;
              }
          }

     Returning Values

     Only one value can be returned from the called C function and
     should be returned using one of the _ret() functions.  The choice
     of which particular _ret() function to be used is determined by
     the type of data being returned.


     FUNCTION     RETURNS

     _retc()      passes a character string to Clipper - string must be
                  null terminated

     _retclen()   allows you to pass a string which is not null
                  terminated to Clipper by specifying the length of the string

     _retds()     passes a date string to a Clipper date.- string must be
                  null terminated

     _retl()      passes an int to a Clipper logical

     _retnd()     passes a double to Clipper numeric

     _retni()     passes an int to a Clipper numeric

     _retnl()     passes a long to Clipper numeric

     Note that the retxx() functions are not sufficient to pass
     control back to Clipper.  After using one of the above functions
     in order to pass control back to Clipper a C return is required.


     Header files

     EXTEND.H is a header file.  Other header files may be included in
     C routines.  In the example quoted above you will see that
     PLANET.H and NANDEF.H are also included.  The order in which
     include files are cited at the head of a C program is often
     important.  For example, in this case NANDEF.H must appear before
     EXTEND.H.

     While on the subject of header files it should be noted that if
     you intend to call from your C routine functions from a run time
     library which comes with your particular .C. compiler there are
     other header files which may have to be included.  Check your
     compiler manual for details.


     Allocating and Releasing Memory

     When memory is allocated in a C function using _exmgrab() it is
     important that this memory should be released using _exmback()
     before returning control back to Clipper.

     Each time you use _exmgrab() you have to tell it exactly how much
     memory is required.  You can either count up the number of bytes
     needed or you can use the function sizeof().  Sizeof() takes as
     an argument a data type and returns the size of that data type in
     bytes, _exmgrab() takes as an argument a number (or numeric
     expression) and returns a character pointer to an area of memory
     large enough to store that number of bytes.

     So is this how you allocate memory for an array of ten integers?

     intarray = _exmgrab(sizeof(int) * 10);  /* wrong */

     No!  Remember that _exmgrab() returns a character pointer and in
     this example the allocated memory is being used to store an array
     of integers.  You must .typecast. this expression so that it
     returns the correct data type, in this case a pointer to type
     integer.

     intarray = (int *)_exmgrab(sizeof(int) * 10);  /*right*/

     When an attempt has been made to allocate memory you must check
     that this allocation has been successful before proceeding. For
     example,

                                    /* attempt to allocate memory */
          intarray = (int *)_exmgrab(sizeof(int) * 10);

          if (!intarray)            /* if no memory available */
               {
               _retc(ERR_MEMORY);   /* return error number */
               return;
               }

     There is a further complication when it comes to releasing
     memory.  Since _exmback() takes as argument the buffer name and
     size of memory allocated you would expect the syntax to be
     something like this.

     _exmback(intarray,sizeof(int) * 10);    /* wrong */

     However, it must be remembered that intarray is a pointer to type
     integer.  _exmback requires a character pointer.  You must
     .typecast. once more.

     _exmback((unsigned char*)intarray,sizeof(int)*10); /*OK*/

     When allocating and releasing memory use only the above
     functions.  Do not use C library functions such as malloc()
     because in the future these will cause compatibility problems.


     Compiling using Microsoft C 5.1

     To compile a Microsoft C 5.0 function that can be linked with
     Clipper:

     C>CL/c/AL/Zl/Oalt/FPa/Gs <filename>.c

     where:

          CL = the compiler command
          /c = compile without linking
          /AL = set program configuration for large model
          /Zl = remove default (l)ibrary-search records from object file
          /Oalt = control optimisation

           where:
                 a = relax alias checking
                 l = enable loop optimisation
                 t = favor execution speed

          /FPa = floating point alternate library
          /Gs = remove calls to stack checking routine

     For more specific information about using Microsoft C with Clipper
     (Summer '87) please consult your C Reference manual or Clipper manual
     page 11-5.


     Conclusion

     The above has tried to point to some of the areas, such as
     parameter passing and checking, allocation and deallocation of
     memory and returning values from a function where care has to be
     taken when writing C routines for Clipper programs.  The results,
     however, are well worth the effort and can greatly increase the
     functionality of your programs.

Online resources provided by: http://www.X-Hacker.org --- NG 2 HTML conversion by Dave Pearson