Passing String Data

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:

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]);

}