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. Programmers should be aware of the following 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:

Figure 3-1: Handling String Variables in External Code — string_array.c 

C
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
25 
26 
27 
28 
29 
30 
31 
32 
33 
34 
35 
36 
37 
38 
39 
40 
41 
#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; 
    } 
  } 
C
42 
43 
44 
45 
46 
47 
48 
49 
50 
51 
52 
53 
54 
55 
56 
57 
58 
59 
60 
61 
62 
63 
64 
65 
66 
67 
68 
69 
 /* 
  * 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]); 
}