Each element of an IML character matrix is stored as a sequence of characters. All the elements in a character matrix contain the same number of characters; the element length. If the text in an element contains fewer characters than the element length, the element is padded with space characters. Within the SAS server, characters are stored using the character encoding scheme of the server. Within the IML Studio client, characters are always stored as two-byte Unicode characters.
An IML matrix can be either one or two dimensional. A two-dimensional matrix is stored in row-major order. Row-major order means that a matrix is stored one row after another with the elements along a row stored contiguously in memory. Thus, the matrix
"A1" "B1" "C1" "A234" "B234" "C234"
is stored in memory as
"A1 B1 C1 A234B234C234"
In the general case, passing an IML character matrix to a C function is significantly more complex than passing a numeric matrix. One of the reasons for this is that most C functions that take string parameters expect null-terminated character strings, but that is not the form in which IMLPlus stores character matrices. Fortunately, two of the most frequently encountered situations involving character matrices and C functions involve single-element character matrices, and these situations are fairly easy to deal with.
If the C function is designed to use single-byte characters, the type of the C function's parameter should be const char *. Pass the matrix to the function by passing the matrix to the method NextArgIsConstAnsiString of the DllFunction class. IMLPlus will convert the matrix to a Java String object automatically.
If the C function is designed to use Unicode characters, the type of the C function's parameter should be const wchar_t *. Pass the matrix to the function by passing the matrix to the method NextArgIsConstUnicodeString of the DllFunction class.
If the C function is designed to use single-byte characters, the type of the C function's parameter should be char *. Create a Java StringBuffer object and pass it to the method NextArgPairIsAnsiString of the DllFunction class. The buffer length argument to NextArgPairIsAnsiString must be sufficient to contain the string retrieved from the C function. When the C function returns, the IMLPlus program should convert the StringBuffer object to a String object and then assign the String object to an IML character matrix. The following example demonstrates calling the Windows function GetCurrentDirectory:
declare DllFunction func = new DllFunction(); func.Init( "kernel32.dll", "GetCurrentDirectoryA", 2 ); declare StringBuffer sb = new StringBuffer(); func.NextArgPairIsAnsiString( 260, sb ); func.Call_Void(); x = sb.toString(); print x;
If the C function is designed to use Unicode characters, the type of the C function's parameter should be wchar_t *. Create a Java StringBuffer object and pass it to the method NextArgPairIsUnicodeString of the DllFunction class. The buffer length argument to NextArgPairIsUnicodeString must be sufficient to contain the string retrieved from the C function. When the C function returns, the IMLPlus program should convert the StringBuffer object to a String object and then assign the String object to an IML character matrix. The following example demonstrates calling the Windows function GetCurrentDirectory:
declare DllFunction func = new DllFunction(); func.Init( "kernel32.dll", "GetCurrentDirectoryW", 2 ); declare StringBuffer sb = new StringBuffer(); func.NextArgPairIsUnicodeString( 260, sb ); func.Call_Void(); x = sb.toString(); print x;
Note that it is not possible for a C function to allocate memory for a string and then pass a pointer to that memory back to the IMLPlus program. The memory management models of C, Java, and IMLPlus are different and memory allocated in one environment cannot be freed in another. An IMLPlus program that needs to obtain a string from a C function must use either the method NextArgPairIsAnsiString or the method NextArgPairIsUnicodeString.
It is possible to pass a character matrix containing multiple elements to a C function, although it is more complicated than passing a single-element character matrix. The programming statements necessary to accomplish this task appear in the source code to the IMLPlus module DoDialogGetListItemsEx. For information on how to view the source code to an IMLPlus module, see Overview of IMLPlus Module Reference. The technique used by this module is to convert the character matrix to a Java array of type char. The matrix elements are stored in the array one after another as null-terminated strings. A zero character marks the end of the string list.