Returning XLOPERs That Still Need to Be Freed by the DLL

Another common problem occurs when you want to write a function that returns a very large XLOPER (for example, a large array full of strings) as the return value. As described in "Memory Used for XLOPERS" on page 169, you can simply allocate the space for the return value as your own global memory by declaring it static. This works for small return values. But for very large arrays, this can consume quite a bit of memory.

To address this problem, Microsoft Excel allows you to set the xlbitDLLFree bit (0x4000) in the xltype field of the XLOPERs that you return from your functions. To use it, you allocate any extra memory that you need for your XLOPER using your own memory allocation routines. You then set the xlbitDLLFree bit in the xltype field to true (1). Finally, you return a pointer to the XLOPER to Microsoft Excel using the normal return statement. Microsoft Excel automatically copies out the data in the XLOPER; then, it calls back the DLL to give you a chance to free the memory that was allocated. It does this by calling the xlAutoFree function, which your DLL must provide. Microsoft Excel passes one argument, which is the XLOPER that is ready to be freed. See the following example.

LPXLOPER WINAPI GetString(void)
{
    static XLOPER x;

    x.xltype = xltypeStr;
    x.val.str = malloc((size_t)8));

    lstrcpy(x.val.str, "\006Sample");

    x.xltype |= xlbitDLLFree;

    return (LPXLOPER)&x;
}

void WINAPI xlAutoFree(LPXLOPER px)
{
    free(px->val.str);

    return;
}

When the GetString function is called from Microsoft Excel, it allocates memory from the system. Then GetString sets the xlbitDLLFree bit in x.xltype and returns x. When Microsoft Excel sees that this bit is on, it copies out the data it needs and then calls xlAutoFree to free the data. (In this code sample, xlAutoFree is not very robust. In a real application with more than one DLL function, you may want to write a version of xlAutoFree that actually checks the type of the LPXLOPER being passed and uses that information to decide how to free it.) With Windows, make sure that you export xlAutoFree in your .DEF file.