The resbuf structure includes a pointer field, rbnext, for linking result buffers into a list. Result buffers can be allocated statically by declaring them in the application. You do this when only a single result buffer is used (for example, by acedGetVar() and acedSetVar()) or when only a short list is needed. But longer lists are easier to handle by allocating them dynamically, and lists returned by ObjectARX functions are always allocated dynamically. One of the most frequently used functions that returns a linked list is acedGetArgs().
Evaluating External Functions shows the AutoLISP calling format of an external subroutine that takes arguments of three distinct types: a string, an integer, and a real value:
(doit pstr iarg rarg)
The following code segment shows how to implement a function with such a calling sequence. The sample function checks that the argument list is correct and saves the values locally before operating on them (operations are not shown). The example assumes that a previous call to acedDefun() has assigned the external subroutine a function code of 0, and that all functions defined by this application take at least one argument:
// Execute a defined function. int dofun() { struct resbuf *rb; char str[64]; int ival, val; ads_real rval; ads_point pt; // Get the function code. if ((val = acedGetFuncode()) == RTERROR) return BAD; // Indicate failure. // Get the arguments passed in with the function. if ((rb = acedGetArgs()) == NULL) return BAD; switch (val) { // Which function is called? case 0: // (doit) if (rb->restype != RTSTR) { acutPrintf("\nDOIT called with %d type.", rb->restype); acutPrintf("\nExpected a string."); return BAD; } // Save the value in local string. strcpy(str, rb->resval.rstring); // Advance to the next result buffer. rb = rb->rbnext; if (rb == NULL) { acutPrintf("\nDOIT: Insufficient number of arguments."); return BAD; } if (rb->restype != RTSHORT) { acutPrintf("\nDOIT called with %d type.", rb->restype); acutPrintf("\nExpected a short integer."); return BAD; } // Save the value in local variable. ival = rb->resval.rint; // Advance to the last argument. rb = rb->rbnext; if (rb == NULL) { acutPrintf("\nDOIT: Insufficient number of arguments."); return BAD; } if (rb->restype != RTREAL) { acutPrintf("\nDOIT called with %d type.", rb->restype); acutPrintf("\nExpected a real."); return BAD; } // Save the value in local variable. rval = rb->resval.rreal; // Check that it was the last argument. if (rb->rbnext != NULL) { acutPrintf("\nDOIT: Too many arguments."); return BAD; } // Operate on the three arguments. . . . return GOOD; // Indicate success break; case 1: // Execute other functions. . . . } }