docs.intersystems.com
Home  /  Application Development: Language Bindings and Gateways  /  Using the Callin API  /  The Callin Interface


Using the Callin API
The Callin Interface
[Back]  [Next] 
InterSystems: The power behind what matters   
Search:  


InterSystems IRIS™ offers a Callin interface you can use from within C programs to execute InterSystems IRIS commands and evaluate ObjectScript expressions. This chapter describes this interface and includes the following sections:
The Callin interface permits a wide variety of applications. For example, you can use it to make ObjectScript available from an integrated menu or GUI. If you gather information from an external device, such as an Automatic Teller Machine or piece of laboratory equipment, the Callin interface lets you store this data in an InterSystems IRIS database. Although InterSystems IRIS currently supports only C and C++ programs, any language that uses the calling standard for that platform can invoke the Callin functions.
See Using the Callin Functions for a quick review of Callin functions. For detailed reference material on each Callin function, see the Callin Function Reference.
The iris-callin.h Header File
The iris-callin.h header file defines prototypes for these functions, which allows your C compiler to test for valid parameter data types when you call these functions within your program. You can add this file to the list of #include statements in your C program:
#include "iris-callin.h"
The iris-callin.h file also contains definitions of parameter values you use in your calls, and includes various #defines that may be of use. These include operating-system–specific values, error codes, and values that determine how InterSystems IRIS behaves.
You can translate the distributed header file, iris-callin.h. However, iris-callin.h is subject to change and you must track any changes if you create a translated version of this file. InterSystems Worldwide Support Center does not handle calls about unsupported languages.
Return values and error codes
Most Callin functions return values of type int, where the return value does not exceed the capacity of a 16-bit integer. Returned values can be IRIS_SUCCESS, an InterSystems IRIS error, or a Callin interface error.
There are two types of errors:
iris-callin.h defines symbols for all system and interface errors, including IRIS_SUCCESS (0) and IRIS_FAILURE (-1). You can translate InterSystems IRIS errors (positive integers) by making a call to the Callin function IrisErrxlate.
8-bit and Unicode String Handling
InterSystems Callin functions that operate on strings have both 8-bit and Unicode versions. These functions use a suffix character to indicate the type of string that they handle:
For best performance, use the kind of string native to your installed version of InterSystems IRIS.
8-bit String Data Types
InterSystems IRIS supports the following data types that use local 8-bit string encoding:
The type definition for these is:
#define IRIS_MAXSTRLEN 32767
typedef struct {
   unsigned short  len;
   Callin_char_t   str[IRIS_MAXSTRLEN];
} IRIS_ASTR, *IRIS_ASTRP;
The IRIS_ASTR and IRIS_ASTRP structures contain two elements:
IRIS_MAXSTRLEN is the maximum length of a string that is accepted or returned. A parameter string need not be of length IRIS_MAXSTRLEN nor does that much space have to be allocated in the program.
2–byte Unicode Data Types
InterSystems IRIS supports the following Unicode-related data types on platforms that use 2–byte Unicode characters:
The type definition for these is:
typedef struct {
   unsigned short len;
   unsigned short str[IRIS_MAXSTRLEN];
} IRISWSTR, *IRISWSTRP;
The IRISWSTR and IRISWSTRP structures contain two elements:
IRIS_MAXSTRLEN is the maximum length of a string that is accepted or returned. A parameter string need not be of length IRIS_MAXSTRLEN nor does that much space have to be allocated in the program.
On Unicode-enabled versions of InterSystems IRIS, there is also the data type IRIS_WSTRING, which represents the native string type on 2–byte platforms. IrisType returns this type. Also, IrisConvert can specify IRIS_WSTRING as the data type for the return value; if this type is requested, the result is passed back as a counted Unicode string in a IRISWSTR buffer.
4–byte Unicode Data Types
InterSystems IRIS supports the following Unicode-related data types on platforms that use 4–byte Unicode characters:
The type definition for these is:
typedef struct {
   unsigned int len;
   wchar_t str[IRIS_MAXSTRLEN];
} IRISHSTR, *IRISHSTRP;
The IRISHSTR and IRISHSTRP structures contain two elements:
IRIS_MAXSTRLEN is the maximum length of a string that is accepted or returned. A parameter string need not be of length IRIS_MAXSTRLEN nor does that much space have to be allocated in the program.
On Unicode-enabled versions of InterSystems IRIS, there is also the data type IRIS_HSTRING, which represents the native string type on 4–byte platforms. IrisType returns this type. Also, IrisConvert can specify IRIS_HSTRING as the data type for the return value; if this type is requested, the result is passed back as a counted Unicode string in a IRISHSTR buffer.
System-neutral Symbol Definitions
The allowed inputs and outputs of some functions vary depending on whether they are running on an 8-bit system or a Unicode system. For many of the “A” (ASCII) functions, the arguments are defined as accepting a IRISSTR, IRIS_STR, IRISSTRP, or IRIS_STRP type. These symbol definitions (without the “A” , “W”, or “H”) can conditionally be associated with either the 8-bit or Unicode names, depending on whether the symbols IRIS_UNICODE and IRIS_WCHART are defined at compile time. This way, you can write source code with neutral symbols that works with either local 8-bit or Unicode encodings.
The following excerpt from iris-callin.h illustrates the concept:
#if defined(IRIS_UNICODE) /* Unicode character strings */
#define   IRISSTR      IRISWSTR
#define   IRIS_STR     IRISWSTR
#define   IRISSTRP     IRISWSTRP
#define   IRIS_STRP    IRISWSTRP
#define   IRIS_STRING  IRIS_WSTRING

#elif defined(IRIS_WCHART)  /* wchar_t character strings */
#define   IRISSTR      IRISHSTR
#define   IRIS_STR     IRISHSTR
#define   IRISSTRP     IRISHSTRP
#define   IRIS_STRP    IRISHSTRP
#define   IRIS_STRING  IRIS_HSTRING

#else                  /* 8-bit character strings */
#define   IRISSTR      IRIS_ASTR
#define   IRIS_STR     IRIS_ASTR
#define   IRISSTRP     IRIS_ASTRP
#define   IRIS_STRP    IRIS_ASTRP
#define   IRIS_STRING  IRIS_ASTRING
#endif
Using InterSystems Security Functions
Two functions are provided for working with InterSystems IRIS passwords:
There are IrisSecureStart and IrisChangePassword functions for ASCII "A", Unicode "W", and Unicode "H" installs. The new functions either narrow, widen or "use as is" the passed in parameters, store them in the new Callin data area, then eventually call the IrisStart entry point.
IrisStart and IrisSecureStart pin and pout parameters can be passed as NULL, which indicates that the platform's default input and output device should be used.
Using Callin with Multithreading
InterSystems IRIS has been enhanced so that Callin can be used by threaded programs running under some versions of Windows and UNIX® (see “Other Supported Features” in the online InterSystems Supported Platforms document for this release for a list). A program can spawn multiple threads (pthreads in a UNIX® environment) and each thread can establish a separate connection to InterSystems IRIS by calling IrisSecureStart. Threads may not share a single connection to InterSystems IRIS; each thread which wants to use InterSystems IRIS must call IrisSecureStart. If a thread attempts to use a Callin function and it has not called IrisSecureStart, a IRIS_NOCON error is returned.
A threaded application must link against irist.o or the shared library, irist.so. On UNIX® and Linux they may alternatively load the shared library dynamically. On Windows, due to the implementation of thread local storage the irist.dll library cannot be dynamically loaded. The program should be careful not to exit until all of the threads which have entered InterSystems IRIS have called IrisEnd to shut down their connections. Failure to shut down each connection with IrisEnd may hang the instance, requiring a restart.
If IrisSecureStart is being used, to specify credentials as part of the login, each thread must call IrisSecureStart and provide the correct username/password for the connection, since credentials are not shared between the threads. There is a performance penalty within InterSystems IRIS using threads because of the extra code the C compiler has to generate to access thread local storage (which uses direct memory references in non-threaded builds).
A sample program, sampcallint.c, is provided on all platforms where this feature is supported. The vc8 project, and the UNIX® Makefiles, include instructions to build a sample threaded Callin application on the relevant platforms.
Threads and UNIX® Signal Handling
On UNIX®, InterSystems IRIS uses a number of signals. If your application uses the same signals, you should be aware of how InterSystems IRIS deals with them. All signals have a default action specified by the OS. Applications may choose to leave the default action, or can choose to handle or ignore the signal. If the signal is handled, the application may further select which threads will block the signal and which threads will receive the signal. Some signals cannot be blocked, ignored, or handled. Since the default action for many signals is to halt the process, leaving the default action in place is not an option. The following signals cannot be caught or ignored, and terminate the process:
SIGNAL DISPOSITION
SIGKILL terminate process immediately
SIGSTOP stop process for later resumption
The actions that an application establishes for each signal are process-wide. Whether or not the signal can be delivered to each thread is thread-specific. Each thread may specify how it will deal with signals, independently of other threads. One thread may block all signals, while another thread may allow all signals to be sent to that thread. What happens when a signal is sent to the thread depends on the process-wide handling established for that signal.
Signal Processing
InterSystems IRIS integrates with application signal handling by saving application handlers and signal masks, then restoring them at the appropriate time. Signals are processed in the following ways:
Generated signals
InterSystems IRIS installs its own signal handler for all generated signals. It saves the current (application) signal handler. If the thread catches a generated signal, the signal handler disconnects the thread from InterSystems IRIS, calls the applications signal handling function (if any), then does pthread_exit.
Since signal handlers are process-wide, threads not connected to InterSystems IRIS will also go into the signal handler. If InterSystems IRIS detects that the thread is not connected, it calls the application handler and then does pthread_exit.
Synchronous Signals
InterSystems IRIS establishes signal handlers for all synchronous signals, and unblocks these signals for each thread when the thread connects to InterSystems IRIS (see Synchronous Signals for details).
Asynchronous Signals
InterSystems IRIS handles all asynchronous signals that would terminate the process (see Asynchronous Signals for details).
Save/Restore Handlers
The system saves the signal state when the first thread connects to it. When the last thread disconnects, InterSystems IRIS restores the signal state for every signal that it has handled.
Save/Restore Thread Signal Mask
The thread signal mask is saved on connect, and restored when the thread disconnects.
Synchronous Signals
Synchronous signals are generated by the application itself (for example, SIGSEGV). InterSystems IRIS establishes signal handlers for all synchronous signals, and unblocks these signals for each thread when it connects to InterSystems IRIS.
Synchronous signals are caught by the thread that generated the signal. If the application has not specified a handler for a signal it has generated (for example, SIGSEGV), or if the thread has blocked the signal, then the OS will halt the entire process. If the thread enters the signal handler, that thread may exit cleanly (via pthread_exit) with no impact to any other thread. If a thread attempts to return from the handler, the OS will halt the entire process. The following signals cause thread termination:
SIGNAL DISPOSITION
SIGABRT process abort signal
SIGBUS bus error
SIGEMT EMT instruction
SIGFPE floating point exception
SIGILL illegal instruction
SIGSEGV access violation
SIGSYS bad argument to system call
SIGTRAP trace trap
SIGXCPU CPU time limit exceeded (setrlimit)
Asynchronous signals
Asynchronous signals are generated outside the application (for example, SIGALRM, SIGINT, and SIGTERM). InterSystems IRIS handles all asynchronous signals that would terminate the process.
Asynchronous signals may be caught by any thread that has not blocked the signal. The system chooses which thread to use. Any signal whose default action is to cause the process to exit must be handled, with at least one thread eligible to receive it, or else it must be specifically ignored.
The application must establish a signal handler for those signals it wants to handle, and must start a thread that does not block those signals. That thread will then be the only one eligible to receive the signal and handle it. Both the handler and the eligible thread must exist before the application makes its first call to IrisStart. On the first call to IrisStart, the following actions are performed for all asynchronous signals that would terminate the process:
The following signals are affected by this process:
SIGNAL DISPOSITION
SIGALRM timer
SIGCHLD blocked by threads
SIGDANGER ignore if unhandled
SIGHUP ignore if unhandled
SIGINT ignore if unhandled
SIGPIPE ignore if unhandled
SIGQUIT ignore if unhandled
SIGTERM If SIGTERM is unhandled, InterSystems IRIS will handle it. On receipt of a SIGTERM signal, the InterSystems IRIS handler will disconnect all threads and no new connections will be permitted. Handlers for SIGTERM are not stacked.
SIGUSR1 inter-process communication
SIGUSR2 inter-process communication
SIGVTALRM virtual timer
SIGXFSZ InterSystems IRIS asynchronous thread rundown
Callin Programming Tips
Topics in this section include:
Tips for All Callin Programs
Your external program must follow certain rules to avoid corrupting InterSystems IRIS data structures, which can cause a system hang.
Tips for Windows
These tips apply only to Windows.
Tips for UNIX® and Linux
These tips apply only to UNIX® and Linux.
Running Sample Programs on Windows
The \dev\iris\callin directory contains source files, header files, and project directories for building InterSystems Callin applications. These projects provide a simple demonstration of how to use some high level InterSystems IRIS call-in functions.
In order to build these projects, open any of the .vcproj files (for Visual C++ 2005), or .dsp files (for Visual C++ 2003). Double-click on the file, or run your Visual C++ application and select File>Open>Project/Solution to open the project file.
Note:
You can run call-in programs on Windows 2000, but you have to compile them on Windows XP or newer, since Visual Studio 2008 and the Windows 2008 SDK only go back to Windows XP. The Visual Studio 2008 redistributables are supported on Windows 2000, but there does not appear to be a compatible compiler that is supported on Windows 2000.
The shdir.c file has been already initialized with the path to your InterSystems IRIS mgr directory. For a default installation, the shdir.c file will look like this:
char shdir[256] = "c:\\irissys\\mgr";
The Callin interface provides the IRISSETDIR entry point to dynamically set the name of the manager directory at runtime. The shared library version of iris requires the use of this interface to find the installation’s manager’s directory.
Two sample C programs are provided. The sampcallin.c program is the standard Callin application example, and sampcallint.c is the thread-safe Callin application example.
There are two projects for sampcallin.c and a project for sampcallint.c. These projects are:
After each of the projects is built, it may be run in the Visual C++ environment.
When a project is built from the iris shared library, using irisdb.dll, the location of iris.dll must be defined in the user's PATH environment variable, except when the file is located in the current directory.
Running Sample Programs on UNIX® and Linux
The directory dev/iris/callin/sample contains a complete Makefile to build Callin sample applications.
A shared library version of iris is now provided in addition to the iris object file. The UNIX® Makefiles build two Callin sample applications: one using the iris object, and one using the libiris shared library.
Run make in the dev/iris/callin/samples directory. The supplied Makefile will build a version of iris using the czf interface, a standard Callin application, and a shared library Callin application.
The file shdir.c is set to the appropriate value during installation, so no editing is required.
The Callin interface provides the IRISSETDIR entry point to dynamically set the name of the manager directory at runtime.
Using Makefiles on UNIX®
The UNIX® Makefiles for building Callin sample demos and customer Callin programs are run by the make command. make automatically finds the file called Makefile in the current directory. Thus, running make in the sample directory produces a sample Callin executable.
When invoking make, use the SRC variable to specify the name of the source program. The default is sampcallin. To change the name of the source file being built, override the SRC variable on the command line. For example, with a Callin program called mycallin.c, the command is:
   make SRC=mycallin
Setting Permissions for Callin Executables on UNIX®
InterSystems IRIS executables, files, and resources such as shared memory and operating system messages, are owned by a user selected at installation time (the installation owner) and a group with a default name of irisusr (you can choose a different name at installation time). These files and resources are only accessible to processes that either have this user ID or belong to this group. Otherwise, attempting to connect to InterSystems IRIS results in protection errors from the operating system (usually specifying that access is denied); this occurs prior to establishing any connection with InterSystems IRIS.
A Callin program can only run if its effective group ID is irisusr. To meet this condition, one of the following must be true: