The CALL_EXTERNAL function calls a function in an external sharable object and returns a scalar value. Parameters can be passed by reference (the default) or by value. See See for examples.
CALL_EXTERNAL is supported under all systems operating systems supported by IDL, although there are system specific details of which you must be aware. This function requires no interface routines and is much simpler and easier to use than the LINKIMAGE procedure. However, CALL_EXTERNAL performs no checking of the type and number of parameters. Programming errors are likely to cause IDL to crash or to corrupt your data.
Input and output actions should be performed within IDL code, using IDL's built-in
input/output facilities, or by using IDL_Message() . Using external code options for
input and output, such as stdin or stdout, may generate unexpected results.
CALL_EXTERNAL supports the
IDL Portable convention
, a portable calling convention that works on all platforms. This convention passes two arguments to the called routine, an argument count (
) and an array of arguments (
). On non-VMS systems, this is the only available convention. Under VMS, the VMS LIB$CALLG convention is also available,. This convention, which is the default, uses the VMS LIB$CALLG runtime library routine to call functions without requiring a special (
The result of the CALL_EXTERNAL function is a scalar value returned by the external function. By default, this is a scalar integer, unless the D_VALUE, F_VALUE, or S_VALUE keywords are specified, indicating that the function returns a double-precision floating-point, single-precision floating-point, or string value, respectively.
Under VMS the full interpretation of this argument is discussed in VMS CALL_EXTERNAL and LIB$FIND_IMAGE_SYMBOL .
The parameters to be passed to the external routine. All array and structure arguments are passed by reference (address). The default is to also pass scalars by reference, but the ALL_VALUE or VALUE keywords can be used to pass them by value. Care must be taken to ensure that the type, structure, and passing mechanism of the parameters passed to the external routine match what it expects. There are some restrictions on data types that can be passed by value, and the user needs to be aware of how IDL passes strings. Both issues discussed in further detail below.
The Microsoft Windows operating system has two distinct system defined standards that govern how routines pass arguments:
, which is used by much of the operating system as well as languages such as Visual Basic, and
, which is used widely for programming in the C language. These standards differ in how and when arguments are pushed onto the system stack. The standard used by a given function is determined when the function is compiled, and can usually be controlled by the programmer. If a function is called using the wrong standard (e.g. calling a
function as if it were
, or the reverse), incorrect results may result, including memory corruption or even IDL crashing. Unfortunately, there is no way for IDL to know which convention a given function uses, this information must be supplied by the user of CALL_EXTERNAL. If the CDECL keyword is present, IDL will use the
convention to call the function. Otherwise,
This keyword is ignored on non-VMS platforms. Under VMS, it is a string containing the default device, directory, file name, and file type information for the file that contains the sharable image. See VMS CALL_EXTERNAL and LIB$FIND_IMAGE_SYMBOL for additional information.
Under VMS, causes CALL_EXTERNAL to use the IDL Portable calling convention for passing arguments to the called function instead of the default VMS LIB$CALLG convention. Under other operating systems, only the portable convention is available, so this keyword is quietly ignored. The details of these calling conventions are described in Calling Convention .
A byte array, with as many elements as there are optional parameters, indicating the method of parameter passing. Arrays are always passed by reference. If parameter P i is a scalar, it is passed by reference if VALUE[ i ] is 0; and by value if it is non-zero. There are some restrictions on data types that should be considered when using this keyword, as discussed below.
If specified, all data passed to the called function is first converted to VAX F (single) or D (double) floating point formats. On return, any data passed by reference is converted back to the IEEE format used by IDL. This feature allow you to call code compiled to work with earlier versons of IDL, which used the old VAX formats.
The default setting for this keyword is FALSE, unless IDL was started with the VAX_FLOAT startup option, in which case the default is TRUE. See Command Line Options for details on this qualifier. You can change this setting at runtime using the VAX_FLOAT function.
Translation of floating-point values from the IDL's native (IEEE) format to the VAX format and back (IEEE to VAX to IEEE) is not a completely reversable operation, and should be avoided when possible. There are many cases where the recovered values will differ from the original, including:
To pass a string by reference, IDL passes the address of its IDL_STRING descriptor. To pass a string by value the string pointer (the
field of the descriptor) is passed. Programmers should be aware of the following when manipulating IDL strings:
slenfield contains the length of the string without including the NULL termination
stypefield is used internally by IDL to know keep track of how the memory for
sis the pointer to the actual C string represented by the descriptor. If the string is NULL,
CALL_EXTERNAL supports two distinct calling conventions for calling user-supplied routines. The primary convention is the IDL Portable convention, which is supported on all platforms. The second is the VMS LIB$CALLG convention which is only available under VMS.
The portable interface convention passes all arguments as elements of an array of C void
pointers (void *). The C language prototype for a user function called this way looks like one of the following:
Where RET_TYPE is one of
. The return type used must agree with the type assumed by CALL_EXTERNAL, as specified by the D_VALUE, F_VALUE, and S_VALUE keywords.
is the number of arguments, and the vector
contains the arguments themselves, one argument per element. Arguments passed by reference map directly to these (
) pointers, and can be cast to the proper type and then dereferenced directly by the called function. Passing arguments by value is allowed, but since the values are passed in (
) pointers, there are some limitations and restrictions on what is possible:
The LIB$CALLG calling convention is built directly upon the VMS LIB$CALLG runtime library function. This function allows calling functions with a natural interface without requiring a special (
) convention. In Fortran, a typical routine might be declared:
As with the Portable convention described above, the return type for the function must be one of the four types:
. It is possible to pass arguments of any data type by reference, but there are some limitations and restrictions on passing arguments by value. Unfortunately, the interface to LIB$CALLG was designed explicitly for the VAX hardware architecture, and does not provide sufficient information to the operating system to pass all data types by value properly on ALPHA Risc CPUs which pass arguments in registers as well as on the system stack. To the best of our knowledge, Digital Equipment Corporation has no plans to supply an updated version of LIB$CALLG that does not have these limitations. Therefore, this calling convention has the following restrictions on ALPHA/VMS:
The LIB$CALLG calling convention is the default for VMS IDL because it was the original convention supported on that platform, and because it allows calling routines that do not adhere to the (
) style interface required by the portable convention. The Portable convention, described above, can be used under VMS by setting the PORTABLE keyword. If you are writing external code to be used under operating systems other than VMS, using the portable interface simplifies cross platform development.
The VMS implementation of CALL_EXTERNAL uses the system runtime library function LIB$FIND_IMAGE_SYMBOL to perform the dynamic linking. This function has a complicated interface in which the name of the library to be linked is given in two separate arguments. We encourage VMS users wishing to use CALL_EXTERNAL to read and fully understand the documentation for LIB$FIND_IMAGE_SYMBOL in order to understand how it is used by IDL. The following discussion assumes that you have a copy of the LIB$FIND_IMAGE_SYMBOL documentation available to consult as you read.
LIB$FIND_IMAGE_SYMBOL uses an argument called filename to specify the name of the sharable library or executable to be loaded. This means that none of the file specification punctuation characters (:, [, <, ;, .) are allowed. Filename can also be a logical name, in which case its translated value is the name of the file to be loaded. The translation of such a logical name is allowed to contain additional file specification information. VMS uses this information to find the file to load, using SYS$SHARE as the default location if a location is not specified via a logical name. Alternatively, the user can supply the image-name argument, which is used as a "default filespec" to fill in the parts of the file specification not contained in filename. IDL uses the following rules, in the order listed, to determine how to call LIB$FIND_IMAGE_SYMBOL:
.) then it is passed to LIB$CALL_IMAGE_SYMBOL as it's filename argument without any further interpretation.
This means that although LIB$CALL_IMAGE_SYMBOL has a complicated interface, the CALL_EXTERNAL user can supply a simple file specification for Image and it will be properly loaded by IDL. Full control of LIB$CALL_IMAGE_SYMBOL is still available for those who require it.