Author Topic: SBT  (Read 35403 times)

0 Members and 1 Guest are viewing this topic.

JRS

  • Guest
Re: SBT
« Reply #60 on: April 30, 2015, 04:06:05 PM »
Since these embedding routines (scriba_NewSbString, ...) return a pSbData pointer, maybe I should define my ArgData array structure as pSbData rather than SbData like I'm doing now. I'm also thinking to maintain thread safe management of all SB variables, the scriba_NewSbLong, scriba_NewSbDouble, scriba_NewSbString and scriba_DestroySbData routines should be used and not  assign the ArgData[0]v.* structure element directly. (Read-Only)

At this point I'm trying to understand why these functions exist and when they should be used. I have to believe Peter created them to ease the pain of what is under the SB API (macro/define) covers and gluing it all together.

Charles Pegge

  • Guest
Re: SBT
« Reply #61 on: April 30, 2015, 04:45:25 PM »
John,

I confirm you can use scriba_NewSbString to create individual string arguments, but you will need to copy them into a single block, yet scriba_DestroySbData for each of them after callArgEx.

Better to use scriba_NewSbArgs, since it builds the arguments in one contiguous block, returning one base pointer, as required by CallArgEx
« Last Edit: April 30, 2015, 05:04:20 PM by Charles Pegge »

JRS

  • Guest
Re: SBT
« Reply #62 on: April 30, 2015, 05:03:48 PM »
Excellent!

Can whip up an example (in O2 is fine) showing your proof of concept?


Charles Pegge

  • Guest
Re: SBT
« Reply #63 on: April 30, 2015, 05:07:52 PM »
For individual String Args / hand-built argument block:

Code: OxygenBasic
  1.   'TEST 4
  2.  'RELOCATE STRING ARGS
  3.  sbData da[4]
  4.   sys a[4]
  5.   a[0] = scriba_NewSbString(pProgram,"ten")
  6.   copy @da[0],a[0],sizeof da
  7.   a[1] = scriba_NewSbString(pProgram,"twenty")
  8.   copy @da[1],a[1],sizeof da
  9.   a[2] = scriba_NewSbString(pProgram,"thirty")
  10.   copy @da[2],a[2],sizeof da
  11.   a[3] = scriba_NewSbString(pProgram,"forty")
  12.   copy @da[3],a[3],sizeof da
  13.   args=@da
  14.  
  15.   count=4
  16.   iError=scriba_CallArgEx(pProgram, sbfun, @ReturnData, count, args)
  17.   'scriba_DestroySbArgs(pProgram,args,4)
  18.  '
  19.  for i=0 to 3
  20.     scriba_DestroySbData(pProgram,a[i])
  21.   next
  22.  
  23.  

JRS

  • Guest
Re: SBT
« Reply #64 on: April 30, 2015, 05:20:31 PM »
Thanks Charles!

I'll give this method a try.

Is this an either or choice?

Code: OxygenBasic
  1.   'scriba_DestroySbArgs(pProgram,args,4)
  2.  '
  3.  for i=0 to 3
  4.     scriba_DestroySbData(pProgram,a[i])
  5.   next
  6.  

JRS

  • Guest
Re: SBT
« Reply #65 on: April 30, 2015, 06:08:12 PM »
Quote
Better to use scriba_NewSbArgs, since it builds the arguments in one contiguous block, returning one base pointer, as required by CallArgEx

I agree if there was a way to wrap a SB variadic function. I think we are bound to using the scriba_NewSbString (and like SB make variable type functions) method and building an ArgData array manually. (dynamically)

Update

Got it working. Still need to return a generic script result.

Thanks Charles! You have been reinstated to super hero status.  ;D
« Last Edit: April 30, 2015, 10:32:00 PM by John »

Charles Pegge

  • Guest
Re: SBT
« Reply #66 on: May 01, 2015, 12:57:18 AM »
John,

I think this is how the whole thing should go, including the returned arg and its destruction.

Code: OxygenBasic
  1.   'CALL A FUNCTION WITH ARGS AND RETURN VALUE
  2.  '------------------------------------------
  3.  '
  4.  string funn="main::callbacka" 'LOWERCASE OF FUNCTION NAME
  5.  pr+="call " funn cr
  6.  
  7.   '
  8.  sbfun=scriba_LookupFunctionByName(pProgram,funn)
  9.   if sbfun=0 then print "Unable to locate " funn : goto ending
  10.   sbData *arg
  11.   sbData *argr
  12.   sys    count=4
  13.   @arg = scriba_NewSbArgs(pProgram," s s s s", "one","two","three","four")
  14.   @argr = scriba_NewSbArgs(pProgram,"u",0)
  15.   scriba_CallArgEx(pProgram, sbfun, argr, count, arg)
  16.  
  17.   'READ RETURN VALUE
  18.  '-----------------
  19.  '
  20.  #semicolon separator
  21.  
  22.   switch (argr.typ) {
  23.     case SBT_UNDEF  : pr+= "Undefined "       ; break ;
  24.     case SBT_DOUBLE : pr+="double "  argr.dbl ; break ;
  25.     case SBT_LONG   : pr+="long "    argr.lng ; break ;
  26.     case SBT_STRING : pr+="zstring " argr.str ; break ;
  27.     case SBT_ZCHAR  : pr+="zchar "   argr.lng ; break ;
  28.   }
  29.   '
  30.  'DESTROY ARGUMENTS AND RETURNED ARG
  31.  scriba_DestroySbArgs(pProgram, arg,count)
  32.   scriba_DestroySbArgs(pProgram, argr,1)
  33.  

JRS

  • Guest
Re: SBT
« Reply #67 on: May 01, 2015, 01:42:48 AM »
For O2, C or other compiled hosts, looks GREAT!

It won't work in an SB extension module as I'm wrapping SB functions and not calling them directly. (no dynamic variadic function support)

I still don't understand how to return a dynamic value as a ArgData mortal variable. I haven't had any luck doing multiple besRETURN_ in an IF block for this.  :o


Charles Pegge

  • Guest
Re: SBT
« Reply #68 on: May 01, 2015, 02:40:20 AM »
In C terms, because argr is an sbdata pointer, you will need to use arrow notation to access the returned members:

argr->lng instead of argr.lng
argr->str instead of argr.str

array notation:

argr[0].lng is equivalent to argr->lng


JRS

  • Guest
Re: SBT
« Reply #69 on: May 01, 2015, 08:01:40 AM »
Thanks Charles!

Did you review the latest working version on All BASIC and do you see any problems with the way I'm doing this?


Working !!! (see All BASIC forum)

« Last Edit: May 01, 2015, 12:04:45 PM by John »

JRS

  • Guest
Re: SBT
« Reply #70 on: May 01, 2015, 02:17:45 PM »
For individual String Args / hand-built argument block:

Code: OxygenBasic
  1.   'TEST 4
  2.  'RELOCATE STRING ARGS
  3.  sbData da[4]
  4.   sys a[4]
  5.   a[0] = scriba_NewSbString(pProgram,"ten")
  6.   copy @da[0],a[0],sizeof da
  7.   a[1] = scriba_NewSbString(pProgram,"twenty")
  8.   copy @da[1],a[1],sizeof da
  9.   a[2] = scriba_NewSbString(pProgram,"thirty")
  10.   copy @da[2],a[2],sizeof da
  11.   a[3] = scriba_NewSbString(pProgram,"forty")
  12.   copy @da[3],a[3],sizeof da
  13.   args=@da
  14.  
  15.   count=4
  16.   iError=scriba_CallArgEx(pProgram, sbfun, @ReturnData, count, args)
  17.   'scriba_DestroySbArgs(pProgram,args,4)
  18.  '
  19.  for i=0 to 3
  20.     scriba_DestroySbData(pProgram,a[i])
  21.   next
  22.  
  23.  

Since I'm not creating a[] and assigning my ArgData array directly , I have no a[] to destroy with scriba_DestroySbData. Is my understanding correct that when SB_CallSubArgs exits, ArgData gets destroyed doing the job for us?


Charles Pegge

  • Guest
Re: SBT
« Reply #71 on: May 01, 2015, 02:31:57 PM »
Hi John,

Glad you were able to crack the return data.

If you create sbNewStrings, my understanding is that you have to destroy each one afterwards. That is why I kept the handles in a[..]

JRS

  • Guest
Re: SBT
« Reply #72 on: May 01, 2015, 02:45:03 PM »
Quote
If you create sbNewStrings, my understanding is that you have to destroy each one afterwards. That is why I kept the handles in a[..]

My understanding of the scriba_DestroySbData function is to release the memory used to temporarily hold the variable structures used in the wrapper function. Since I'm using the destination ArgData[] as the storage area and it get destroyed when the function exits, all is good, correct?

On the other hand if we care about Peter's MyAlloc memory manager, the function should probably be called.
« Last Edit: May 01, 2015, 02:55:46 PM by John »

Charles Pegge

  • Guest
Re: SBT
« Reply #73 on: May 01, 2015, 03:15:23 PM »
I did a quick test to see what happened to the arg strings after CallArgex, and yes, they appear to be already released!

JRS

  • Guest
Re: SBT
« Reply #74 on: May 01, 2015, 03:31:54 PM »
That is really good news!

It could also explain my core dumps with the following attempt as releasing the ArgData structures after assignment.

Code: C
  1. besFUNCTION(SB_CallSubArgs)
  2.   DIM AS VARIABLE Argument;
  3.   DIM AS SbData ArgData[8];
  4.   DIM AS SbData TmpArg;
  5.   DIM AS SbData FunctionResult;
  6.   DIM AS unsigned long sbobj;
  7.   DIM AS int i, slen, fnsn;
  8.  
  9.   Argument = besARGUMENT(1);
  10.   besDEREFERENCE(Argument);
  11.   sbobj = LONGVALUE(Argument);
  12.  
  13.   Argument = besARGUMENT(2);
  14.   besDEREFERENCE(Argument);
  15.   fnsn = LONGVALUE(Argument);
  16.  
  17.   for( i=3 ; i <= (unsigned)besARGNR ; i++ ){
  18.     Argument = besARGUMENT(i);
  19.     besDEREFERENCE(Argument);
  20.     switch( slen=TYPE(Argument) ){
  21.       case VTYPE_LONG:
  22.         TmpArg = scriba_NewSbLong(sbobj, LONGVALUE(Argument));
  23.         ArgData[i-3] = *TmpArg;
  24.         scriba_DestroySbData(sbobj,TmpArg);
  25.         break;
  26.       case VTYPE_DOUBLE:
  27.         TmpArg = scriba_NewSbDouble(sbobj, DOUBLEVALUE(Argument));
  28.         ArgData[i-3] = *TmpArg;
  29.         scriba_DestroySbData(sbobj,TmpArg);
  30.         break;
  31.       case VTYPE_STRING:
  32.         TmpArg = scriba_NewSbString(sbobj, STRINGVALUE(Argument));
  33.         ArgData[i-3] = *TmpArg;
  34.         scriba_DestroySbData(sbobj,TmpArg);
  35.         break;
  36.     }
  37.   }
  38.  
  39.   scriba_CallArgEx(sbobj, fnsn, &FunctionResult, besARGNR-2, &ArgData);
  40.  
  41.   switch (FunctionResult.type) {
  42.     case SBT_LONG   :
  43.         besRETURN_LONG(FunctionResult.v.l);
  44.         break ;
  45.     case SBT_DOUBLE :
  46.         besRETURN_DOUBLE(FunctionResult.v.d);
  47.         break ;
  48.     case SBT_STRING :
  49.         besRETURN_STRING(FunctionResult.v.s);
  50.         break ;  
  51.   }
  52. besEND
  53.  

Thanks for the conformation/comfort in knowing.