Copyright © TIBCO Software Inc. All Rights Reserved
Copyright © TIBCO Software Inc. All Rights Reserved


Chapter 3 Accessing External Routines : External Routines in C

External Routines in C
Steps Required to Use an External C Routine
Syntax Mapping
The osextusr.h required header file, available in the install_path\extrc\include folder, is used to map TIBCO Object Service Broker syntax to C syntax. It contains a list of the supplied functions used to manipulate the arguments passed to TIBCO Object Service Broker. It must be in your include library during compilation.
How are Exceptions Handled?
There are no exceptions trapped during external routine invocation and execution, such as, if the external routine is not found or it fails. A message is written to the message log and a traceback is generated if a failure occurs.
Procedural Overview
The major tasks in preparing and executing an external C routine are:
1.
2.
When these tasks are completed, a TIBCO Object Service Broker rule can invoke the external routine.
If your Execution Environment is multi-threaded (that is, the MAXSESSION Execution Environment parameter is greater than 1), your external routines must be reentrant and thread-safe.
 
Task A Coding, compiling, and linking your program
Coding the External Routine
The external routine implementation must comply with the following C prototype:
void user_routine (HRN_EXT_PARAM param);
The same prototype is used whether your routine is a function or a straight procedure.
Key Elements  The key elements in the prototype are:
 
Sample Routines for Compiling and Linking under Windows  The following contains a set of sample external routines for Windows. As noted in the comments, they implement a function rule and a procedure rule:
/*************************************************************/
/* Sample External Routines */
/* */
/*************************************************************/
 
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
 
/* Include all the supplied access routines for manipulating
   the arguments passed from TIBCO Object Service Broker.   */
#include "osextusr.h"
/**************************************************************
   This function accepts two arguments: a cost and a tax rate.
   It returns the cost with the tax applied. If an access
   routine fails (indicated by the return of a value of -1)
   the external routine returns immediately.
**************************************************************/
 
void userFunc (HRN_EXT_PARAM param)
{
   double cost;
   double tax_rate;
   double taxed_cost;
 
   /* Get first argument. */
   if (hrnGetDoubleArg (param, 1, &cost))
     {
       return;
     }
   /* Get second argument. */
   if (hrnGetDoubleArg (param, 2, &tax_rate))
      {
         return;
      }
   /* Calculate total cost with tax. */
   taxed_cost = cost + cost * tax_rate;
   /* Set returned value. Returned value is placed in
      parameter in position 0.*/
   if (hrnSetDoubleArg (param, 0, taxed_cost))
      {
         return;
      }
}
void userProc (HRN_EXT_PARAM param)
/**************************************************************
   This function accepts one arguments: a string. It modifies
   the string by concatenating "HELLO WORLD". If an access
   routine fails (indicated by the return of a value of -1) the
   external routine returns immediately.
**************************************************************/
{
   char      *pszstring;
   char      *concat_string = "HELLO WORLD";
   int      concat_string_length = 11;
   int      string_length;
   /* Get the length of the string argument.
   If a negative string length is returned,
   the access function failed - return immediately. */
   string_length = hrnGetCharArgLen (param, 1);
   if (string_length <= 0)
      {
         return;
      }
   /* Allocate and initialize memory for the length of the
   string plus the concatenation string length plus the
   trailing '\0' character. Return if unable to allocate the
   memory.                                          */
   pszstring = malloc (
      string_length + concat_string_length + 1);
   if (!pszstring)
      {
         return;
      }
   memset (pszstring, 0,
      string_length + concat_string_length + 1);
   /* Get string argument. Concatenate "HELLO WORLD" to
   the string.                                       */
   if (hrnGetCharArg (param, 1, pszstring,
      string_length + 1))
      {
         return;
      }
   strcat (pszstring, concat_string);
/* Replace the argument with the modified string.*/
   if (hrnSetCharArg (param, 1, pszstring))
      {
         return;
      }
}
Sample Import/Export Definitions File  The sample code for the Import/Export definitions (test.def) is:
LIBRARY Test
EXPORTS
      USERFUNC = userFunc
      USERPROC = userProc
In this example, the mixed-case symbol names userFunc and userProc are exported uppercase (USERFUNC and USERPROC), as required by LOADNAME field of the ROUTINES table. Refer to Identifying the external routine to TIBCO Object Service Broker, page 27 for more information.
Sample Routines for Compiling and Linking under Solaris  The following contains a set of sample external routines for Solaris:
#include "osextusr.h"
 
#if defined(__cplusplus)
extern "C" {
#endif
 
void EXTRTEST (HRN_EXT_PARAM param)
{
   int op1;
   int op2;
   int sum;
 
   if (hrnGetIntArg (param, 1, &op1))
      return;
 
   if (hrnGetIntArg(param, 2, &op2))
      return;
   sum = op1 + op2;
 
   if (hrnSetIntArg(param, 0, sum))
      return;
}
 
#if defined(__cplusplus)
} // extern "C"
#endif
Compiling and Linking
The routine must be compiled as 32-bit code by a compiler that can produce:
External Routine for the Windows Platform  The external routine DLL can be built with any compiler able to produce 32-bit code compatible with the Microsoft Visual C++ runtime environment. The DLL must be linked with the osextusr.lib import library.
Compiling and Linking External Routines on Solaris  On Solaris, external routines are compiled as shared libraries. Use the following commands to create a C++ version of the shared libraries.
In this example, install_path refers to the TIBCO Object Service Broker installation folder:
g++ -c -o extrtest.o -fPIC -D_POSIX_C_SOURCE=199506L\
   -U_XOPEN_SOURCE -D_XOPEN_SOURCE -D__EXTENSIONS__ -D_REENTRANT\
   -I<install_path>/extrc/include extrtest.c
g++ -o libextrtest.so -shared extrtest.o
Dynamic Linking
So that external routines can call functions external to TIBCO Object Service Broker, the libraries containing these functions must reside in the search path for osMon. In Windows, this is in the PATH environment variable. In Solaris, this is in the LD_LIBRARY_PATH.
Task B Identifying the external routine to TIBCO Object Service Broker
Specify the Table Entries
The external routine and its load module name are identified to TIBCO Object Service Broker through an entry in the ROUTINES table. If the routine has arguments, these are specified in a table instance of the ARGUMENTS table. Ensure that you have adequate security to insert data into these tables before editing them.
Use the Table Editor to add information to these tables. To use this option, enter the required table name beside the ED edit table option on the workbench and press Enter to display the table.
Add an Entry in the ROUTINES Table
The following illustration shows an extract of the ROUTINES table. You must scroll right using PF11 to see additional fields.

 
EDITING TABLE : ROUTINES
COMMAND ==>
SCROLL: P
NAME LANGUAGE FUNCTION TYPE SYNTAX LENGTH DECIMAL
_ ---------------- ---------------- - - - ------ ------
_ ABEND N 0 0
_ ADMCHART N 0 0
_ ASMS_ASTRANSLATE N 0 0
_ ASREAD N 0 0
_ BINARY_TO_LOGIC Y L C 1 0
_ BTOPACKD Y C 1 0
_ CATROW N 0 0
_ CCOB11 N 0 0
_ CCOB12A N 0 0
_ CCOB12B N 0 0
_ CDIR50O N 0 0
_ USERFUNC Y Q P 5 2
_ USERPROC N 0 0
 
 
 
PFKEYS: 4=INSERT 16=DELETE 5=FIND NEXT 6=CHG NEXT 18=EXCLUDE 3=SAVE 12=CANCEL

 
Type the appropriate information about your external routine in fields of the ROUTINES table, as described:
 
The language in which the external routine is written. This field is used for descriptive purposes only and is not required.
Syntax: C, Length: 16
If the external routine is a function, specify the TIBCO Object Service Broker semantic type of the value returned.
Syntax: C, Length: 1
If the external routine is a function, specify the TIBCO Object Service Broker syntax of the value returned.
Syntax: C, Length: 1
If the external routine is a function that returns a value with digits to the right of the decimal, specify the number of digits.
Syntax: B, Length: 2
This name must be exported uppercase in the exports definition file. The symbol to be loaded can be lowercase or mixed case in the external routine, but it must be exported uppercase to the LOADNAME field.
The point when the external library is unloaded. At present the only valid value is SESSION (that is, the external library must be unloaded when the session ends).
NODENAME can be either left blank or set to @SESSION, meaning that the C routine executes in the same process as the Execution Environment.
Syntax: V, Length: 255
Specify the full path name of the C routine. It must be a dynamic link library for Windows or a shared object library for Solaris.
Syntax: V, Length: 255
Sample Entry
The single occurrence from the ROUTINES table for the routine XYZ follows. In this example USERFUNC, whose source code you can find in Coding the External Routine, is called as a function.

 
--- SINGLE OCCURRENCE EDITOR ---
EDITING TABLE : ROUTINES
TABLE TYPE : TDS
COMMAND ==>
------------------------------------------------------------------------------
NAME : USERFUNC
LANGUAGE : C
FUNCTION : Y
TYPE : Q
SYNTAX : P
LENGTH : 5
DECIMAL : 2
LOADNAME USERFUNC
SCOPE : Session
NODENAME : @SESSION
                 :
                 :
                 :
                 :
LIBNAME : D:\Test\dir\test.dll
:
PFKEYS: 1=HELP 2=DOCUMENTATION 3=SAVE 12=CANCEL 13=PRINT 22=DELETE

 
Add an Entry in the ARGUMENTS Table
If your external routine has arguments, to identify the arguments to TIBCO Object Service Broker add a table instance to the ARGUMENTS table. The parameter value for the table instance of the ARGUMENTS table must be the name of the external routine (that is, the value in the NAME field of the ROUTINES table). You can have a maximum of 16 arguments.
The instance of the ARGUMENTS table for the sample routine XYZ follows:

 
EDITING TABLE : ARGUMENTS(USERFUNC)
COMMAND ==>
SCROLL: P
NUMBER NAME INOUT TYPE SYNTAX LENGTH DECIMAL
_ ------ ---------------- - - - ------ ------
_ 1 COST N Q P 5 2
_ 2 TAX_RATE N Q P 2 2
 
PFKEYS: 4=INSERT 16=DELETE 5=FIND NEXT 6=CHG NEXT 18=EXCLUDE 3=SAVE 12=CANCEL
At TOP

 
Type the appropriate information in the fields of the ARGUMENTS table:
 
The position of the argument in the argument list. The positions must be sequential and start at 1.
Syntax: B, Length: 2
The argument name.
Syntax: C, Length: 16
Whether the value of the argument can be changed by the external routine. If it can be changed, the value passed to the routine must be a local variable or the field of a table and the field must have the same data definition as the argument. Valid entries are Y or N.
Syntax: C, Length: 1
The argument syntax.
Syntax: C, Length: 1
The argument length.
Syntax: B, Length: 2
See Also
TIBCO Object Service Broker Managing Data for information about how to use the Table Editor.
TIBCO Object Service Broker Programming in Rules about valid TIBCO Object Service Broker syntax and semantic data types.

Copyright © TIBCO Software Inc. All Rights Reserved
Copyright © TIBCO Software Inc. All Rights Reserved