IDL represents strings internally as IDL_STRING descriptors. For more information about IDL_STRING, see IDL Internals: Variables and IDL Internals: String Processing. These descriptors are defined in the C language as:

typedef struct { IDL_STRING_SLEN_T slen; 
   unsigned short stype; 
   char *s;
} IDL_STRING;

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 s field of the descriptor) is passed. When manipulating IDL strings:

  • Called code should treat the information in the passed IDL_STRING descriptor and the string itself as read-only, and should not modify these values.
  • The slen field contains the length of the string without including the NULL termination that is required at the end of all C strings.
  • The stype field is used internally by IDL to keep track of how the memory for the string was obtained, and should be ignored by CALL_EXTERNAL users.
  • s is the pointer to the actual C string represented by the descriptor. If the string is NULL, IDL represents it as a NULL (0) pointer, not as a pointer to an empty null terminated string. Hence, called code that expects a string pointer should check for a NULL pointer before dereferencing it.
  • You must use the functions discussed in IDL Internals: String Processing to allocate the memory for an IDL_STRING. Attempting to do this directly by allocating dynamic memory and assigning it to the IDL_STRING descriptor is a common pitfall, as discussed in Common CALL_EXTERNAL Pitfalls.

Returning a String Value


When returning a string value, a function must allocate the memory used to hold it. On return, IDL will copy this string. You can use a static buffer or dynamic memory, but do not return the address of an automatic (stack-based) variable.

Note: IDL will not free dynamically-allocated memory for this use.

Example


The following routine, found in string_array.c, demonstrates how to handle string variables in external code. This routine takes a string or array of strings as input and returns a copy of the longest string that it received. It is important to note that this routine uses a static char array as its return value, which avoids the possibility of a memory leak, but which must be long enough to handle the longest string required by the application. This is implemented as a function with a natural C interface, and a second glue routine that implements the IDL portable convention, using the one with the natural interface to do the actual work:

 

 #include <stdio.h>
 #include <string.h>
 #include "idl_export.h"
   /*
  	* IDL_STRING is declared in idl_export.h like this:
  	*	typedef struct {
  	*	IDL_STRING_SLEN_T slen;	Length of string, 0 for null
  	*	short stype;	Type of string, static or dynamic
  	*	char *s;	Address of string
  	* } IDL_STRING;
  	* However, you should rely on the definition in idl_export.h instead
  	* of declaring your own string structure.
  	*/
 
	char* string_array_natural(IDL_STRING *str_descr, IDL_LONG n)
	{
  	/*
  	* IDL will make a copy of the string that is returned (if it is
  	* not NULL). One way to avoid a memory leak is therefore to return
  	* a pointer to a static buffer containing a null terminated string.
  	* IDL will copy the contents of the buffer and drop the reference
  	* to our buffer immediately on return.
  	*/
	#define MAX_OUT_LEN 511	/* truncate any string
	longer than this */
	static char result[MAX_OUT_LEN+1];	/* leave a space for a ’\0’
	on the longest string */
	int max_index;	/* index of longest string */
	int max_sofar;	/* length of longest string*/
	int i;
 
	/*	Check the size of the array passed in. n should be > 0.*/
	if (n < 1) return (char *) 0;
	max_index = 0;
	max_sofar = 0;
	for(i=0; i < n; i++) {
  	if (str_descr[i].slen > max_sofar) {
  	max_index = i;
  	max_sofar = str_descr[i].slen;
	}
	}
 
  /*
  * If all strings in the array are empty, the longest
  * will still be a NULL string.
  */
if (str_descr[max_index].s == NULL) return (char *) 0;
  /*
  * Copy the longest string into the buffer, up to MAX_OUT_LEN
  * characters.
  * Explicitly store a NULL byte in the last byte of the buffer,
  * because strncpy() does not NULL terminate if the string copied
  * is truncated.
  */
strncpy(result, str_descr[max_index].s, MAX_OUT_LEN);
result[sizeof(result)-1] = ’\0’;
return(result);
#undef MAX_OUT_LEN
}
char* string_array(int argc, void* argv[])
{
  /*
  * Make sure there are the correct	# of arguments.
  * IDL will convert the NULL into an empty string (’’).
  */
if (argc != 2) return (char *) NULL;
return string_array_natural((IDL_STRING *) argv[0], (IDL_LONG) argv[1]);
}