Where is the memory used for XLOPERs allocated and freed? First, consider the simple case in which Microsoft Excel calls a function in a DLL that returns a value. Microsoft Excel allocates and frees the arguments it passes, so you don't have to worry about them.
The only potential problem is the return value. If your function returns a simple value, there is no problem using the normal C return value. However, sometimes your function needs to return an XLOPER. That XLOPER may be contained in 10 bytes as usual, but it might also have pointers to large blocks of data that are stored elsewhere. The simplest way to return such data is to allocate some static memory and return a pointer to the memory. Following is an example for Windows of a simple DLL that returns a string XLOPER.
LPXLOPER WINAPI ReturnString(void)
{
static XLOPER x;
x.xltype = xltypeStr;
x.val.str = "\004Test";
return (LPXLOPER) &x;
}
Next, consider the case in which the DLL calls a Microsoft Excel function using Excel4. Again, the caller (the DLL) allocates the arguments. The caller must allocate 10 bytes for the return value XLOPER as well, and a pointer to this XLOPER is passed as the second argument to Excel4 so that Microsoft Excel knows where to place the return value.
This works for simple XLOPERs without any pointers. But what happens when Excel4 must return a string? The XLOPER contains a pointer to memory that has been allocated by Microsoft Excel from its own memory management system. You need to let Microsoft Excel know when you are finished with that data so that Microsoft Excel can free its memory. This is done using the xlFree function, which takes one or more XLOPERs and tells Microsoft Excel that it can free any associated memory.
For example, if the XLOPER is a string, calling xlFree on it frees the string, not the XLOPER itself. Similarly, if the XLOPER is an array of strings, xlFree frees everything except the top-level XLOPER. To summarize, whenever Excel4 returns an XLOPER containing a pointer, you must call xlFree on that XLOPER.
Note
In Excel 97 calling xlFree on an XLOPER containing an xltypeMulti will change the xltype of the XLOPER to xltypeMissing. This is a change from previous versions of Excel.
A safe rule is to call xlFree on every return value you get back from Excel4. If you pass xlFree an XLOPER that does not contain a pointer, nothing happens. If xlFree is accidentally called twice on the same XLOPER, Microsoft Excel ignores the second call.
Do not modify XLOPERs that you get back from Microsoft Excel. If you do, the Microsoft Excel memory manager will not be able to free them properly and may crash.
The following example uses the xlFree function to return a string.
/*
** Use Microsoft Excel to get input from the user,
** then copy it into our own memory space.
*/
XLOPER xQuery, xResponse, x2;
static unsigned char rgchResult[64] = "";
unsigned char i;
xQuery.xltype = xltypeStr;
xQuery.val.str = "\022What is your name?";
x2.xltype = xltypeNum;
x2.val.num = 2;
Excel4(xlfInput, &xResponse, 2, (LPXLOPER) &xQuery, (LPXLOPER) &x2);
if (xResponse.xltype == xltypeStr)
{
/*
** Now Microsoft Excel has allocated memory for the
** string in its own memory space. Copy the string out
** to our own memory, while converting to a C
** (null-terminated) string.
*/
for (i=1;
(i <= (unsigned char)xResponse.val.str[0]) && (i < 64);
i++)
{
rgchResult[i - 1] = xResponse.val.str[i];
}
rgchResult[i - 1] = '\0';
}
/*
** Let Microsoft Excel free the string from its memory.
*/
Excel4(xlFree, 0, 1, (LPXLOPER) &xResponse);