Question
· Nov 29, 2017

Callout - how to get something beyond simple datatype (or return several datatypes)

Is there a way to get one of:

  • Struct
  • $lb
  • Subscripted local variable
  • List/array

As a return type from callout call?

And related question: is there a way to return several values (which may contain commas) from one callout call.  Or rather what's the best approach when doing that?

Consider the following example:

#define ZF_DLL
#include "cdzf.h"
#include <stdio.h>

int GetTwoStrings(char* a, char* b, char* retval) {
    sprintf(b,"%s",a);
    sprintf(retval,"%s",a);
    return ZF_SUCCESS; 
}

ZFBEGIN
   ZFENTRY("GetTwoStrings","1c1C1C",GetTwoStrings)
ZFEND

And the corresponding Caché code:

ClassMethod GetTwoStrings(a) As %String
{
    set b=""
    set path = "libsimplecallout.dll"
    set retval = $ZF(-3, path, "GetTwoStrings", a, b)
    zw a, b, retval
}

When I execute GetTwoStrings I get the following output:

do ..GetTwoStrings("my,Text")
a="my,Text"
b=""
retval="my,Text,my,Text"

retval returned from callout call contains both b and retval from C, but what's the best approach on parsing it into separate variables?

Discussion (4)1
Log in or sign up to continue

JSON format is probably the most general. Return the values in a JSON formatted string. Then parse with

    SET objresult=##CLASS(%DynamicObject).%FromJSON(result)

However, if you want to return a simple structure. That is two or a few values, where no values are themselves structures, and nature of the data is easily understood, you could return the values as an artificial local reference, and take the value apart with $QSUBSCRIPT() is COS. This function would prove handy for such an option.

/* This function adds %q to snprintf() to print a quoted string. */
int varcosreturn (char *buffer, size_t len, char *fmt, ...) {
   va_list ap;
   char *p, *q, *r;
   char c;
   size_t n;
   char xfmt [3];

   va_start(ap, fmt);
   p = buffer; q = fmt;
   for (;;) {
      c = *q++;
      if (c == '\0') break;
      if (c != '%') { if (len==0) break; --len; *p++ = c; continue; }
      c = *q++;
      if (c == 'q') {
         if (len==0) break; --len; *p++ = '\"';
         r = va_arg(ap,char*);
         for (;;) {
            c = *r++;
            if (c == '\0') break;
            if (c == '\"') { if (len==0) break; --len; *p++ = '\"'; }
            if (len==0) break; --len; *p++ = c;
         }
         if (len==0) break; --len; *p++ = '\"';
         continue;
      }
      xfmt [0] = '%'; xfmt [1] = c; xfmt [2] ='\0';
      n = snprintf (p, len, xfmt, va_arg(ap, void*));
      len -= n; p += n;
   }
   va_end(ap);
   if (len==0) return -1; --len; *p++ = '\0';
   return 0;
}

$LISTBUID() format is not doucmented so that InterSystems can later expand (or change) it.