Application Development

Chapter 20. Writing C Functions

This chapter presents an overview on:

Additional information is in Chapter 44, "Installed Event Functions."

Types of C Functions

Your own C code can be written in external files and linked to your Panther clients (prodev[.exe], or prorun[.exe]), your Panther application servers, or your Panther Web application servers (jserver[.exe]).

There are two types of C functions in Panther:

Even though there can only be one automatic function for each event type, a Panther object can have both an automatic function and a demand function. For example, when a screen opens, any automatic screen function executes, and the screen can have a demand function specified in the Screen Entry property which also executes.

Using Automatic Functions

Each type of automatic function, such as an automatic screen function or automatic group function, must be:

The following data structure from funclist.c is for an automatic screen function:

struct fnc_data autosc_struct = SM_OLDFNC( 0, auto_sfunc);

For a list of the SM_*FNC macros, refer to "SM_*FNC Macro."

funclist.c also contains the function sm_do_uinstalls, which is called internally by Panther at the beginning of program execution. This function should contain calls to sm_install for all the types of functions you install. Calls for all of the automatic functions must be added to the sm_do_uinstalls function.

For example, placing the following line of code in the sm_do_uinstalls function would install the automatic screen function listed above.

sm_install ( DFLT_SCREEN_FUNC, &autosc_struct, (int *)0 );

For a further explanation of the arguments to this function and a list of function types, refer to Table 44-1.

Using Demand Functions

Demand functions must also be located in a data structure in funclist.c. funclist.c provides empty data structures for screen, group, field, tab card, grid, control string, and prototyped functions. By adding your demand function to the appropriate data structure, you will insure that the function is automatically installed. All the data structures provided in funclist.c already have calls to install them into Panther inside the sm_do_uinstalls function, that is also in funclist.c.

To determine the appropriate structure, you need to determine whether the function uses standard arguments or non-standard arguments. Any function using non-standard arguments must be installed into the prototyped functions data structure.

For example, if you write a screen function which needs to know that the screen is being opened (rather than closed, since the automatic screen function executes on both screen entry and screen exit), that information can be found in the screen function's standard parameters. Since the function would use the default parameters, you could add the function to the screen data structure and the function would not need to be prototyped. However, the function's parameters would need to match the number and data type of all the standard arguments passed by default to standard screen functions. Also, this function could only be called on screen entry and exit, because only then will the automatic parameters be generated appropriately.

For prototyped functions, you declare the number and type of arguments. Panther supports a function receiving any combination of strings and integers from zero to five arguments, and functions with six integer arguments.

(If you wish to pass floating point values, pass them as strings and then convert appropriately inside your function. The same method of passing the parameter as a string must be used for all non-integer data-types.) Functions return types can be either character string, integer, double or void.

If a function's arguments do not conform to these requirements—for example, there are more than six, or they include an unsupported data type—you can call it indirectly through a wrapper function.

Writing C Functions

To add your own C code to your application, you must:

It is strongly suggested that you copy your Panther distribution and work in the copy of the distribution when adding C code. At a minimum you should always make a backup of the link directory before making changes to any file in that directory. Or, alternatively, work with a copy of the link directory and leave the original link directory unchanged.

For example, to write a simple C function that opens a dialog box to say "Hello World" and link it to Panther, perform the following steps:

  1. In the link directory, create the C code in an external file. The sample file, mycode.c, contains:
    #include "smdefs.h" 
    int printhello() 
    	sm_message_box("Hello World", "My Installed Function",
           SM_MB_OK, "")
    	return (0);
  2. In the include directory, create the header file. The sample header file, myapp.h, contains:
    extern int printhello									PROTO(());

    Notes: PROTO is a macro function designed to generate prototypes compatible with both ANSI and pre-ANSI C compilers. If you know your compiler is ANSI-compatible, you could also write this as "extern int printhello( void );".

  3. In the link directory, edit funclist.c. First, at the top of funclist.c, list your header file with the other header files. The header files listed in the sample funclist.c are:
    #include "smdefs.h"
    #include "smkeys.h"
    #include "myapp.h"  /* my installed function */
  4. In funclist.c, add your function to one of the Panther C structures. Since this function does not use standard arguments, it is entered as a prototyped function. With this new function, the data structure appears as follows:
    static struct fnc_data pfuncs[] =
       SM_INTFNC ("pdummy(i)",             pdummy),
       SM_INTFNC ("printhello()",          printhello)
  5. In funclist.c, the call to sm_install already occurs for prototyped functions, so there is no need to make your own call.
  6. In the link directory, modify your makefile to compile and link your code into Panther:
    SRCMODS = funclist.o mycode.o 
  7. Compile and link your application:

    UNIX: make
    Windows: nmake

  8. Restart your development executable:

Additional information on writing and installing C functions is in Chapter 44, "Installed Event Functions."

Calling C Functions

Once your C routine is linked into Panther, you can use the JPL call command in JPL procedures, such as:

call printhello()

Or you can call your function from one of the widget or screen event properties, by setting the property value to match your C function name.

Entry Function							printhello()

Since your function does not take the standard arguments for screen or widget functions, including the ()'s overrides the standard arguments and the function will be called with no arguments.

You can also use C functions in JPL to assign values to variables using the following syntax:

x = getsum(1, 3)

Calling Panther Library Functions

Panther has an extensive C function library. By default, the entire Panther C library is linked into your development and runtime executables. Most of the C function names start with the prefix sm_; some database interface functions start with dm_.

A given C function can have several variants. For example, sm_gofield has the following variants:

In functions having an object name as one of the arguments, the object's name, the object's identifier or the object's property specifier can be entered. For example:

sm_n_getfield ("@id(15)")
sm_n_getfield ("@screen("@current")->title_id")

Refer to Chapter 5, "Library Functions," in Programming Guide for documentation about each Panther C function.