I figured it out. A couple of things to note here -
You need to make sure that your UDF registration is using the right signature. In my case, I wanted Excel references to give me their respective values, so I used the Q
type when registering the function. If you don't understand this, check out http://msdn.microsoft.com/en-us/library/office/bb687869.aspx
In order to return an array, you have to dynamically allocate new memory to the list.val.array.lparray
member and iteratively populate it.
__declspec(dllexport) LPXLOPER12 WINAPI array_cons(VARG_DEF_LIST(VARG_MAX)) {
LPXLOPER12 vargs[] = GET_VARGS;
int args_passed = 0;
for(int i = 0; i < VARG_MAX; ++i, ++args_passed) {
if (vargs[i]->xltype == xltypeMissing) {
break;
}
}
XLOPER12 list;
list.xltype = xltypeMulti | xlbitDLLFree;
list.val.array.lparray = new XLOPER12[args_passed];
list.val.array.rows = args_passed;
list.val.array.columns = 1;
for(int i = 0; i < args_passed; ++i) {
list.val.array.lparray[i] = *vargs[i];
}
return &list;
}
Since we are dynamically allocating memory, we need to define the callback to free it.
__declspec(dllexport) void WINAPI xlAutoFree12(LPXLOPER12 p) {
if (p->xltype == (xltypeMulti | xlbitDLLFree)) {
delete [] p->val.array.lparray;
}
}