Try OpenEdge Now
skip to main content
Programming Interfaces
External Program Interfaces : Host Language Call Interface : Example HLC application
 

Example HLC application

This section explains how to use the OpenEdge HLC tank demo application. This application is a prepackaged application that you can use to verify that your HLC environment is set up correctly. The C code and sample output for this example are provided in the $DLC/oebuild/hlc/examples directory on UNIX, and in the %DLC%\oebuild\hlc\examples directory in Windows.
Set up your environment and compile this example before you try to run it to verify that your compiler and the OEBuild utility are working correctly. This also helps you learn how to use HLC in a controlled environment.
This sample application uses OpenEdge to keep track of oil storage tanks. Your ABL procedure calls a C program, AVCALC, to calculate the available capacity for a given tank. The following figure shows that the tanks are cylindrical, with their axes parallel to the level ground.
Figure 68. Tank positioning and orientation
To calculate the available capacity (empty portion) of the tank, you need to know the tank's diameter, length, and current level of oil. Use the variables in the following formula to calculate the available tank volume:
r
Radius of the tank.
length
Length of the tank.
level
Level of oil in the tank.
For this example, assume there is a tank table for this application that contains the following decimal fields:
radius
Radius of tank.
tlength
Length of tank.
depth
Level of oil—must be between 0 and (2 . radius).
tavail
Available volume in tank.
In addition to these fields, the tank-id character field is used as the primary index.
The following example shows the Data Dictionary report for the tank application.
Data Dictionary report for tank application
Default field order: yes
09/10/93                  Data Dictionary Report Page 1
Database: tank
tank File
=========
(Flat file containing oil tank information)
Delete Validation
Criterion:
Message:
Field Type Ext Dec Format Init
------------ ----- --- --- ------------------------------ ----------
* tank-id char x(8)
radius dec 2 ->>,>>9.99 0
tlength dec 2 ->>,>>9.99 0
depth dec 2 ->>,>>9.99 0
tavail dec 2 ->>,>>9.99

Index Name Unique Field Name Seq Ascending abbreviate
------------ ------ ------------ --- --------- ----------
# tank yes tank-id 1 yes yes

Field Validation Criteria, Validation Messages
------------------------------------------------------------------------
depth : depth le 2 * (input radius)
Depth cannot exceed diameter of tank

Help Messages
------------------------------------------------------------------------
tank-id : Tank identification number
radius : Radius of oil tank
tlength : Length of oil Tank
depth : Depth of oil in tank.
tavail : Available Volume In Tank


Data Dictionary Report Legend
* - Indicates that a field participates in an index
# - Indicates the primary index for a database file
M - Indicates that a field is mandatory
A C function calculates the tavail field from the other three decimal fields (radius, tlength, depth). The following example shows the ABL procedure that invokes the C function by calling the HLC routine, AVCALC.
ABL procedure calling HLC routine AVCALC
/* calculate available volume for each tank */
DEFINE NEW SHARED BUFFER tankbuf FOR tank.

FOR EACH tankbuf:
  DISPLAY
    radius SPACE(3) tlength SPACE(3) depth SPACE(3) tavail
    WITH CENTERED TITLE "Tank Table".
END.
PAUSE 0.
VIEW FRAME tank-before.
HIDE ALL.

FOR EACH tankbuf:
  DO TRANSACTION:
    CALL AVCALC.
  END.

  DISPLAY
    radius SPACE(3) tlength SPACE(3) depth SPACE(3) tavail
    WITH CENTERED TITLE "After Calculation".
END.
Make a copy of the HLC dispatch routine, hlprodsp.c, and name it tankdsp.c. Modify the routine so that an entry appears for AVCALC, which calls the C subroutine hlvcalc.
The hlprodsp.c example shows the modifications to the tankdsp.c routine.
hlprodsp.c
#define FUNCTEST(nam, rout) \
if (strcmp(nam, pfunnam) == 0) \
return rout(argc,argv);

/* PROGRAM: PRODSP
*
* This is the interface to all C routines that
* ABL has associated 'call' statements to.
*/
long
PRODSP(pfunnam, argc, argv)
char *pfunnam;
/* Name of function to call */
int argc;
char *argv[];{
/* Interface to 'tank' example */
FUNCTEST ("AVCALC", hlvcalc);

return 1;
}
The following procedure shows the code for the demo program, hlvcalc.c. The program extracts the radius, length, and level fields from the shared buffer tank, calculates the available volume, and updates the tavail field in the shared buffer tank with the number calculated.
hlvcalc.c
* Obtains the height, radius and oil level for the tank
* from the shared buffer "tankbuf".
*
* Calculates the remaining available volume
*
* Update the avail field in the shared buffer "tankbuf" with the
* number calculated.
*/
#define BUFLEN 100
#include <math.h>
#include "hlc.h"
/*NOTE: M_PI_2 is pi/2 constant which may be defined in math.h */
#ifndef M_PI_2
#define M_PI_2 1.570796327
#endif

extern double asin();

char *fieldnm[] = { "tlength", "depth", "radius"};
char message[80];
int
hlvcalc()
{
char buffer[BUFLEN];
int unknown = 0, index = 0, varlen = BUFLEN, actlen;
int ret;
double length, depth, radius, avail;
int i;
int fldpos;
double temp1, temp2; /* used to simplify calculation */
/* first, obtain the length, depth and radius from */
/* the shared buffer "tankbuf". */
for (i = 0; i < 3; ++i)
{
fldpos = profldix("tankbuf", fieldnm[i]);
if (fldpos < 0)
{
sprintf(message, "profldix failed on %s for field %s",
"tankbuf", fieldnm[i]);
promsgd(message);
return 1;
}

ret = prordbn("tankbuf", fldpos, index,
buffer, &unknown, varlen, &actlen);
if (ret)
{
sprintf(message, "prordbn failed accessing %s . %s",
"tankbuf", fieldnm[i]);
promsgd(message);
return 1;
}
/* if one of the fields is unknown, set avail field */
/* to the unknown value */
if (unknown)
{
fldpos = profldix("tankbuf", "tavail");
if (fldpos < 0)
{
sprintf(message, "profldix failed on %s for field %s",
"tankbuf", "tavail");
promsgd(message); return 1;
}
       ret = prowtbn("tankbuf", fldpos, index, buffer, unknown);
if (ret)
{
sprintf(message, "prowtbn failed, ret = %d", ret);
promsgd(message);
return 1;
}
return 0;

/* convert the character string obtained from */
/* ABL into a decimal number */
buffer[actlen] = '\0';

switch (i)
{
case 0:
length = atof(buffer); break;
case 1:
depth = atof(buffer); break;
case 2:
radius = atof(buffer); break;

default:
break;
}
/* Now, calculate the available volume */
/* NOTE: M_PI_2 is pi/2 constant defined in math.h */
#ifndef M_PI_2
#define M_PI_2 1.57
#endif
temp1 = 1.0 - depth/radius;
temp2 = temp1 * sqrt(1.0 - temp1 * temp1) + asin(temp1);
avail = length * radius * radius * (temp2 + M_PI_2);

/* Now, put this value in the tavail field in the */
/* "tankbuf" shared buffer */
/* get the double into character format */
sprintf(buffer, "%.2f", avail);
fldpos = profldix("tankbuf", "tavail");
if (fldpos < 0)
{
sprintf(message, "profldix failed on %s for field %s",
"tankbuf", fieldnm[i]);
promsgd(message);
return 1;
}
ret = prowtbn("tankbuf", fldpos, index, buffer, unknown);
if (ret)
{
sprintf(message, "prowtbn failed, ret = %d", ret);
promsgd(message);
return 1;
}
return 0;
* Running the sample application in Windows
* Running the sample application on UNIX
* Source code listings