Extender SDK - Returning an Array

Started by JTaylor, May 12, 2015, 06:31:06 AM

Previous topic - Next topic

JTaylor

Which macro should I use to return an array from an Extender?   What form does the data need to be in when returning?   Sample code always appreciated :-)

Thanks.

Jim

JTaylor

Thought I figured it out but getting gibberish.   Guess that is better than an outright error :-)

Jim

td

I don't believe there is a macro for returning an WIL array.  You need to fill a LPVIPERVAR structure with the appropriate values and call the ViperCallback function using the function pointer in lpViperCallBack.  That is mostly what the 'RETURN' macros do.

Any examples we might have are written using regrettably obtuse C++ templates that would require some understanding of generic programming to decipher but the basic concept is fairly straight forward and the existing macros are the best example.  The DllArrayServices extender interface callback does all the heavy lifting with regard to initializing your ViperVar (LPVIPERVAR) structure that you pass back to the interpreter via the lpViperCallBack function pointer.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

JTaylor

Assuming I am somewhat on the right track...to what would the "lpstr=str" need to be changed?  Is the rest correct?

lpViperCallback(((lpViperReturn->lpstr=str)   +(lpViperReturn->inittype=VARTYPE_ARRAY))   ?RESULT_SUCCESS:RESULT_SUCCESS, ViperInterfaceVersion, lpViperStruct, lpViperReturn)


Jim

td

Assuming you have a properly created ViperVar variable from a call to
vipervar ArrayVar
lpViperStruct->lpfnDllArrayServices(.., &ArrayVar....)

then you can simply assign all elements of array variable structure to the return variable structure.

*lpViperReturn = ArrayVar

And assuming the ArrayVar is valid, pass the shallow copy of the  array variable back to the interpreter.

return lpViperCallback(RESULT_SUCCESS, ViperInterfaceVersion, lpViperStruct, lpViperReturn);
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

td

Note that you are responsible for freeing the resources allocated to your local copy of the array variable so you will need to hang on to your copy and call lpfnDllArrayServices with request 4 to clean up.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

td

Correction:  You don't need to clean up your local copy of an array variable with  lpfnDllArrayServices with request 4 when you pass the array back the interpreter.  The interpreter will take care of it for you.   
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

JTaylor

I hate to ask but would you PLEASE take pity on me and fix the mess below so it will return an array?  I realize it would help if I knew what I was doing but I am far from that point and my hours of work, while somewhat educational, doesn't seem to be doing much to solve the problem.  At one point I was getting a zero(success) response from the ArrayService call but WinBatch still told me it wasn't an array or some such error.  I finally created a function to simply try to get an array returned rather than the data I want in the array.  My latest iteration is below.   Currently I either get a 7 or a 10 response, depending on what I do with lpBuf.  Thanks.

Jim

Code (winbatch) Select


  vipervar myarr;
  LONG lpBuf;
  LONG afun = 2;

//  LONG DllArrayServices(HGLOBAL hBatData,  &myarr, UINT uVarSize, LPBYTE lpBuf, UINT uBufSize, LONG afun);
     int ret = lpViperStruct->lpfnDllArrayServices(lpViperStruct->hBatData, &myarr, sizeof(vipervar),  (LPBYTE) lpBuf, sizeof(lpBuf), afun);

     MyLtoa(ret,szWork,10);
     MessageBox(hWnd, szWork, "Repsponse Code", MB_OK);

 
  myarr.x      = 111;
  myarr.lpstr  = "Hello";
  myarr.lpstr  = "2015";
  myarr.lpstr  = "2015";
  myarr.lpstr  = "2015";
  myarr.x      = 222;
  myarr.x      = 32;

      *lpViperReturn = myarr;  
 
 
      return lpViperCallback(RESULT_SUCCESS, ViperInterfaceVersion, lpViperStruct, lpViperReturn);


td

First, you need to go to the addons.h file and examine what the DllArrayServices function is expecting for parameters when you use it to create an array.  Once you have that figured out, take a look at the DllArrHandler function in addons.h.  This is the function you use to set and get individual elements from the WIL array after you created it with DllArrayServices. Notice that  it states
about the nrequest parameter.

2  =  set (and clear) value                   (vv = value to set)

Also notice that the element value to set (vv) must be a in a vipervar.  So you need to place the array element value in a vipervar and call the  DllArrhandler with request 2 to add a value to the specified  array location. You specify the elements's location in the array using the subscript parameters of the function.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

JTaylor

Yes.  Have spent a few hours looking at Addons.h and also have the source for the Array Extender and have been perusing that for a clear example.   I'll go back to beating my head against the wall for a few more hours before probably asking the same question again :-)    The vv info is helpful.  Saw that in the Array Extender and thought it was important but wasn't sure in what way.

One thing that would be helpful though...what would I use for the lpBuf?  Not clear what data I will be buffering.  Just a row?  The entire array?  Something else entirely?   Can't recreate whatever I did before to get a successful response on the DllArrayServices call.   Not that it means I was doing it right but I counted it a small victory at the time.

Thanks.

Jim

td

From addons.h DllArrayServices parameter descriptions:

lpBuf     =  buffer for input or output, depending on request (cast to LPBYTE)

and

nRequest  =  operation to perform:
    1  =  get array info    (lpBuf = pointer to DLLARRAYSERVICES1 structure)
    2  =  create array      (lpBuf = pointer to DWORD[5] containing array dimensions <<<<-----------
    3  =  initialize array  (lpBuf = vipervar containing value to set)
    4  =  free array        (lpBuf = 0)
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

JTaylor

If I could read it would probably help  ;)

Thanks.

Jim

JTaylor

I think I just did something REALLY wrong because it works :)

If I keep at this for another 10 years or so it might start making sense.

Thank you VERY much.

Jim

JTaylor

Wondering if someone could point out my problem.   The value before returning from GetWBTime() is correct so I know that value I am passing is correct and everything works.   It is during the "return" that I end up with gibberish.  Have spent a few hours going nowhere so thought I would ask.  Thanks.

Jim


Give this as a prototype:

    LPSTR NEARPASCAL GetWBTime(FILETIME);


Then this call:

LPSTR wbtimec         = "";

wbtimec = GetWBTime(fcreate);

to

Code (winbatch) Select


LPSTR NEARPASCAL GetWBTime(FILETIME fdate)
{

SYSTEMTIME st;
char display[512]    = "";
        char wbtime[19]      = "";
     
        FileTimeToLocalFileTime( &fdate, &fdate );
        FileTimeToSystemTime( &fdate, &st );

        GetDateFormat (LOCALE_USER_DEFAULT, NULL, &st, "yyyy:MM:dd:",  display, 512 );
        strcpy (wbtime, display);
        GetTimeFormat (LOCALE_USER_DEFAULT, NULL, &st, "HH:mm:ss",     display, 512 );
        strcat (wbtime, display);

if (display && display[0] == '\0') {wbtime[0] = (char)"";}
MessageBox(NULL,wbtime,"AS IS",MB_OK);

return (LPSTR) wbtime;

}


td

Yikes. You're returning a pointer to a stack variable.  Can't do that.  You need to either place your return string into dynamically allocated memory and return the pointer or pass in a pointer to a buffer big enough to hold your result.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

JTaylor

Figured it was something like that but just haven't figured out the right combination....to borrow some words..."I know 1,000 ways how NOT to do it" :-)

I'm sure your guidance will get me there though...back to it....thanks again.

Jim