Smart CODE
Your on-line guide to the generated code

My First CGI Application. A worked example


Introduction

This example demonstrates how you can build a X-Designer generated application as a thin-client, where you don't write callbacks directly in the application, but instead write them in a separate server application that can run anywhere.

Writing a callback in the server is very similar to writing a Smart Code callback using getters and setters as we did in the first example. The only difference is that there is a clear division between interface and application issues. The callback on the server is interested only in the values of the controls - in fact it doesn't know about controls at all, simply fields in a data structure. The server program may have to respond correctly to a range of clients, each with different interfaces.

Things you must do/know BEFORE running the example

Environment Variables etc

As always, you should make sure that $XDROOT/bin is in your path.

Here is a summary of the variables you will need to set up before working through the example

XDROOT
LM_LICENSE_FILE

Preparing the Example

Step 1 Create a new directory called, for example, cgiexample
Step 2 Change directory to cgiexample
Step 3 Run xdesigner using the xdreplay script $XDROOT/src/examples/sc/myfirst.vcr, ie

$ xdreplay -f $XDROOT/src/examples/sc/myfirst.vcr xdesigner


This will create the example application, generate the code, copy standard versions of the callbacks you would have written into the appropriate place, and invoke make to build the program.
Step 5The script has produced a client-side program that has a getter function get_myURL(). Since this has to be configured to run on your system, you will need to edit the file

callouts_c/myURL.c

and then reissue the make command.

You can either install the server side program on your internal web server, in the cgi-bin area, and set this routine to return the correct URL to the program, or you can set it to a prebuilt version on IST's web server:

http://www.ist.co.uk/cgi-bin/xd5_cgiexample

If you use our prebuilt version, the software may need to connect across a firewall. While it is possible to customise the application so that it uses a particular proxy host and port, you can achieve the same effect by setting the environment variable HTTP_PROXY. For example, if your proxy host is called meinhost and its port is 8081, you would:

% setenv HTTP_PROXY meinhost:8081

Running the Example

First, check that you have set up the environment variables. If there is a problem, check that they are set correctly, eg

$ ls $XDROOT

You run the example application by typing

$ ./untitled

Every time you press the button, the callback is run in the server and your interface is updated automatically. To prove this, try setting the toggle.

Some words of explanation

Creating the Interface

The application is designed to illustrate how easy it can be to move a callback out of an application, and over to a server - or wherever is appropriate. The interface is trivial, a button to hang the callback on, and a group comprising a toggle and a text field.

Step 1 Create an Application Shell, a form, and underneath it, a button, toggle and text field
Step 2 Click on the toggle, then Shift-click on the text field so they are both selected
Step 3 Select add to new group from the toolbar. Close the group editor when it appears.
Step 4 Select the button, bring up the callbacks dialog, name the callback doit_callback, select Smart/Code- Thin Client. Then press the group button, and in the Group Editor make sure the group is selected, and press apply.
Step 5 The customiser button is now sensitive. Press it to access the Thin Client properties page. when it appears.
Step 6 All you need to do fill out the proxy and port fields if you are behind a firewall and make sure that the URL field refers to the place where you are going to install your server program.

If you are going to use our prebuilt version, you should set this to:


http://www.ist.co.uk/cgi-bin/xd5_cgiexample

As an alternative to configuring the Proxy and Port fields, you can set the environment variable HTTP_PROXY, eg

	% setenv HTTP_PROXY     meinhost:80

Step 7 Apply these changes, closing the properties page, and then press the add button in the callbacks dialog.

Close the callbacks dialog.

Step 8 Use Generate/generate... from the menu bar to get to the code generation page. Make sure that you are generating C, that you are generating to the right directory, and that the default toggles are set including the Stubs generation toggle

Press the generate button.

Step 9 Back in the shell, use make to build the thin-client application and the server, ie

$ make
$ make server

If you want to use the CGI program with your own web server, you should move or link the compiled server program into your server's cgi-bin directory.

If you need to build the server on a different platform, you only need take the Makefile and the server_c directory across. The code in the server_c directory is entirely self contained.

To make the example work, you don't change the client at all. It requires no programming. Simply modify the file server_c/doit_callback.c, replacing the stub callback with the one below.


int
doit_callback  ( sc_data_t * data)
{
	group0_t * g = (group0_t*)data->group;

	if (SC_GET(g->toggle1))
		SC_SET(g->text1, "Hallo World");
	else
		SC_SET(g->text1, "Farewell Cruel World");

	return 1;
}

The callback is very similar to the one we wrote in the first example, where we were using getters and setters directly in the interface. There is, however, one very important difference.

In the client you can access a number of useful properties with the getters and setters. For example, you can change a control's sensitivity as well as take/change its value.

In the server, the control is simply a value. All you can do is read this value and change it. A toggle has a boolean state, a textfield has a string value, etc.

Because of this, you simply get and set the control's value. While in the client you might say


SC_SET(Value,g->text1,"Hallo World");

in the server you simply:

SC_SET(g->text1,"Hallo World");

Notes