xlAutoFree/xlAutoFree12

Область применения: Excel 2013 | Office 2013 | Visual Studio

Вызывается в Microsoft Excel сразу после того, как функция листа XLL возвращает к нейXLOPER12XLOPER/ с установленным флагом, указывающим, что у него есть память, которую XLL по-прежнему необходимо освободить. Благодаря этому библиотека XLL может вернуть динамически выделяемые массивы, строки и внешние ссылки на лист без утечек памяти. Дополнительные сведения см. в статье Управление памятью в Excel.

Начиная с Excel 2007 поддерживаются функция xlAutoFree12 и тип данных XLOPER12 .

Excel не требует XLL для реализации и экспорта любой из этих функций. Однако это необходимо сделать, если функции XLL возвращают xloper или XLOPER12, которые были динамически выделены или содержат указатели на динамически выделенную память. Убедитесь, что выбор способа управления памятью для этих типов согласован в XLL и способе реализации xlAutoFree и xlAutoFree12.

В функции xlAutoFree/ xlAutoFree12 обратные вызовы в Excel отключены, за одним исключением: xlFree можно вызвать для освобождения памяти, выделенной Excel.

void WINAPI xlAutoFree(LPXLOPER pxFree);
void WINAPI xlAutoFree12(LPXLOPER12 pxFree);

Параметры

pxFree (LPXLOPER в случае xlAutoFree)

pxFree (LPXLOPER12 в случае xlAutoFree12)

Указатель на XLOPER или XLOPER12 с памятью, которую необходимо освободить.

Значение свойства и возвращаемое значение

Эта функция не возвращает значение и должна быть объявлена как возвращающая void.

Замечания

Если Excel настроен для использования многопоточного пересчета книги, метод xlAutoFreexlAutoFree12/ вызывается в том же потоке, который используется для вызова функции, возвращающей ее. Вызов функции xlAutoFree/ xlAutoFree12 всегда выполняется перед оценкой последующих ячеек листа для этого потока. Это упрощает потокобезопасную разработку библиотеки XLL.

Если предоставленная функция xlAutoFree/ xlAutoFree12 просматривает поле xltypepxFree, помните, что бит xlbitDLLFree будет по-прежнему задан.

Пример

Пример реализации 1

Первый код из \SAMPLES\EXAMPLE\EXAMPLE.C демонстрирует очень конкретную реализацию xlAutoFree, которая предназначена для работы только с одной функцией , fArray. Как правило, XLL будет иметь более одной функции, возвращающей память, которая должна быть освобождена. В этом случае требуется менее ограниченная реализация.

Пример реализации 2

Реализация второго примера соответствует предположениям, используемым в примерах создания XLOPER12 в разделе 1.6.3, xl12_Str_example, xl12_Ref_example и xl12_Multi_example. Предполагается, что при установке бита xlbitDLLFree вся строка, массив и внешняя эталонная память динамически выделяются с помощью malloc и поэтому должны быть освобождены в вызове free.

Пример реализации 3

Третий пример реализации согласуется с XLL, где экспортированные функции, возвращающие XLOPER12выделяют строки, внешние ссылки и массивы с помощью malloc, а сам XLOPER12 также динамически выделяется. Возврат указателя на динамически выделяемый XLOPER12 — это один из способов обеспечения потоковой безопасности функции.

//////////////////////////////////////////
//       BEGIN EXAMPLE IMPLEMENTATION 1
//////////////////////////////////////////
LPXLOPER12 WINAPI fArray(void)
{
    LPXLOPER12 pxArray;
    static XLOPER12 xMulti;
    int i;
    int rwcol;
    xMulti.xltype = xltypeMulti | xlbitDLLFree;
    xMulti.val.array.columns = 1;
    xMulti.val.array.rows = 8;
    // For large values of rows and columns, this would overflow
    // use __int64 in that case and return an error if rwcol
    // contains a number that won't fit in sizeof(int) bytes
    rwcol = xMulti.val.array.columns * xMulti.val.array.rows; 
    pxArray = (LPXLOPER12)GlobalLock(hArray = GlobalAlloc(GMEM_ZEROINIT, rwcol * sizeof(XLOPER12)));
    xMulti.val.array.lparray = pxArray;
    for(i = 0; i < rwcol; i++) 
    {
        pxArray[i].xltype = xltypeInt;
        pxArray[i].val.w = i;
    }
// Word of caution - returning static XLOPERs/XLOPER12s is not thread safe
// for UDFs declared as thread safe, use alternate memory allocation mechanisms
    return (LPXLOPER12)&xMulti;
}
void WINAPI xlAutoFree12(LPXLOPER12 pxFree)
{
    GlobalUnlock(hArray);
    GlobalFree(hArray);
    return;
}
//////////////////////////////////////////
//       BEGIN EXAMPLE IMPLEMENTATION 2
//////////////////////////////////////////
void WINAPI xlAutoFree12(LPXLOPER12 pxFree)
{
    if(pxFree->xltype & xltypeMulti)
    {
/* Assume all string elements were allocated using malloc, and
** need to be freed using free.  Then free the array itself.
*/
        int size = pxFree->val.array.rows *
            pxFree->val.array.columns;
        LPXLOPER12 p = pxFree->val.array.lparray;
        for(; size-- > 0; p++) // check elements for strings
            if(p->xltype == xltypeStr)
                free(p->val.str);
        free(pxFree->val.array.lparray);
    }
    else if(pxFree->xltype & xltypeStr)
    {
        free(pxFree->val.str);
    }
    else if(pxFree->xltype & xltypeRef)
    {
        free(pxFree->val.mref.lpmref);
    }
}
//////////////////////////////////////////
//       BEGIN EXAMPLE IMPLEMENTATION 3
//////////////////////////////////////////
LPXLOPER12 WINAPI example_xll_function(LPXLOPER12 pxArg)
{
// Thread-safe return value. Every invocation of this function
// gets its own piece of memory.
    LPXLOPER12 pxRtnValue = (LPXLOPER12)malloc(sizeof(XLOPER12));
// Initialize to a safe default
    pxRtnValue->xltype = xltypeNil;
// Set the value of pxRtnValue making sure that strings, external
// references, arrays, and strings within arrays are all dynamically
// allocated using malloc.
//    (code omitted)
//    ...
// Set xlbitDLLFree regardless of the type of the return value to
// ensure xlAutoFree12 is called and pxRtnValue is freed.
    pxRtnValue->xltype |= xlbitDLLFree;
    return pxRtnValue;
}
void WINAPI xlAutoFree12(LPXLOPER pxFree)
{
    if(pxFree->xltype & xltypeMulti)
    {
// Assume all string elements were allocated using malloc, and
// need to be freed using free. Then free the array itself.
        int size = pxFree->val.array.rows *
            pxFree->val.array.columns;
        LPXLOPER12 p = pxFree->val.array.lparray;
        for(; size-- > 0; p++) // check elements for strings
            if(p->xltype == xltypeStr)
                free(p->val.str);
        free(pxFree->val.array.lparray);
    }
    else if(pxFree->xltype & xltypeStr)
    {
        free(pxFree->val.str);
    }
    else if(pxFree->xltype & xltypeRef)
    {
        free(pxFree->val.mref.lpmref);
    }
// Assume pxFree was itself dynamically allocated using malloc.
    free(pxFree);
}

См. также

Функции диспетчера надстроек и интерфейса XLL