Thư viện tri thức trực tuyến
Kho tài liệu với 50,000+ tài liệu học thuật
© 2023 Siêu thị PDF - Kho tài liệu học thuật hàng đầu Việt Nam

Excel Add-in Development in C/C++ Applications in Finance phần 4 pdf
Nội dung xem thử
Mô tả chi tiết
Turning DLLs into XLLs: The Add-in Manager Interface 101
// Free memory allocated by new_xlstring()
free(xStr.val.str);
return 1;
}
Using the C++ xloper class cpp_xloper, introduced in section 6.4, the above code
can be rewritten as follows:
int __stdcall xlAutoRemove(void)
{
cpp_xloper xStr("Version 1.0 has been removed");
cpp_xloper xInt(2); // Dialog box type.
Excel4(xlcAlert, NULL, 2, &xStr, &xInt);
return 1;
}
5.5.5 xlAddInManagerInfo
• xloper * __stdcall xlAddInManagerInfo(xloper *);
Excel calls this function the first time the Add-in Manager is invoked. It should return
an xloper string with the full name of the add-in which is then displayed in the Add-in
Manager dialog (Tools/Add-Ins...). (See example below.) If this function is omitted, the
Add-in Manager dialog simply displays the DOS 8.3 filename of the add-in without the
path or extension.
The function should return 1 to indicate success.
Here is a simple example which uses a DLL function new_xlstring() to create a
byte-counted string that is marked for freeing once Excel has copied the value out.
xloper * __stdcall xlAddInManagerInfo(xloper *p_arg)
{
if(!xll_initialised)
xlAutoOpen();
static xloper ret_oper;
ret_oper.xltype = xltypeErr;
ret_oper.val.err = xlerrValue;
if(p_arg == NULL)
return &ret_oper;
if((p_arg->xltype == xltypeNum && p_arg->val.num == 1.0)
| | (p_arg->xltype == xltypeInt && p_arg->val.w == 1))
{
// Return a dynamically allocated byte-counted string and tell Excel
// to call back into the DLL to free it once Excel has finished.
ret_oper.xltype = xltypeStr | xlbitDLLFree;
ret_oper.val.str = new_xlstring("My Add-in");
}
return &ret_oper;
}
102 Excel Add-in Development in C/C++
Using the C++ xloper class cpp_xloper, introduced in section 6.4, the above code
can be rewritten as follows:
xloper * __stdcall xlAddInManagerInfo(xloper *p_arg)
{
if(!xll_initialised)
xlAutoOpen();
cpp_xloper Arg(p_arg);
cpp_xloper RetVal;
if(Arg == 1)
RetVal = AddinName;
else
RetVal = (WORD)xlerrValue;
return RetVal.ExtractXloper();
}
Invoking the Add-in Manager calls this function resulting in the following being displayed:
5.5.6 xlAutoRegister
• xloper * __stdcall xlAutoRegister(xloper *);
This function is only called from Excel 4 macro sheets when an executing macro encounters an instance of the REGISTER() macro sheet function where information about the
types of arguments and return value of the function are not provided. xlAutoRegister() is passed the name of the function in question and should search for the function’s
arguments and then register the function properly, with all arguments specified. (See
section 8.5 on page 182.) As macro sheets are deprecated, and outside the scope of this
book, this function is not discussed any further. The function can safely either be omitted
or can be a stub function returning a NULL pointer.
Turning DLLs into XLLs: The Add-in Manager Interface 103
5.5.7 xlAutoFree
• void __stdcall xlAutoFree(xloper *);
Whenever Excel has been returned a pointer to an xloper by the DLL with the xlbitDLLFree bit of the xltype field set, it calls this function passing back the same pointer.
This enables the DLL to release any dynamically allocated memory that was associated
with the xloper. Clearly the DLL can’t free memory before the return statement, as
Excel would not safely be able to copy out its contents. The xlAutoFree() function
and the xlbitDLLFree bit are the solution to this problem. (See also Chapter 7 Memory
Management on page 161 for more about when and how to set this bit.)
Returning pointers to xlopers with the xlbitDLLFree bit set is the only way to
return DLL-allocated memory without springing a memory leak. The next-best solution
is to allocate memory, assign it to a static pointer, and free it the next time the function
gets called.
Typically, your DLL will need to contain this function when
• returning DLL-allocated xloper strings;
• returning DLL-allocated range references of the type xltypeRef;
• returning DLL-allocated arrays of xlopers. If the array contains string xlopers that
refer to memory that needs to be freed then xlAutoFree() should do this too. (See
example below.)
There are a few points to bear in mind when dealing with arrays:
• The array memory pointed to by an array xloper can be static or dynamically allocated. The xlbitDLLFree bit should only be set for arrays where the memory was
dynamically allocated by the DLL.
• Array elements that are strings may be static, or may have had memory allocated for
them by either the DLL or Excel.
• Excel will only call xlAutoFree() for an array that has the xlbitDLLFree bit
set, which should be one that was dynamically allocated in the DLL.
• A static array containing dynamic memory strings will leak memory.
• A DLL-created dynamic array containing Excel-allocated strings requires that the
xlbitXLFree bit be set for each string, and xlAutoFree() needs to detect this.
• You should not pass arrays of arrays, or arrays containing references, back to Excel:
your implementation of xlAutoFree() does not need to check for this. (The example
implementation below would, in fact, cope fine with this, but the inclusion of a reference
in an array would confuse and possibly destabilise Excel.)
The following code provides an example implementation that checks for arrays, range
references and strings – the three types that can be returned to Excel with memory still
needing to be freed. The function can call itself recursively when freeing array elements.
For this reason the function checks for an argument that has the xlbitXLFree bit set.
Excel will never call this function for an xloper with this bit set, but this implementation
copes with Excel-created strings in DLL-created arrays.