Author Topic: ScriptBasic O2h Embedding  (Read 26915 times)

0 Members and 3 Guests are viewing this topic.

JRS

  • Guest
ScriptBasic O2h Embedding
« on: April 18, 2011, 09:24:55 PM »
Charles,

I need a little help understanding how ScriptBasic uses it's Dynlolib API to load libraries at runtime. I have been using Gtk-Server for my API scripting efforts but I looking at using SB's built in functions and expand on them with a SB extension module. The API consists of load/release/get function address by name. Is that enough to call functions dynamically? I was wondering if the combination of these internal API calls along with some of the DYC code could be used to make function calls.

ScriptBasic developer Dynlolib API docs

John
« Last Edit: April 18, 2011, 09:42:37 PM by JRS »

Charles Pegge

  • Guest
ScriptBasic O2h Embedding
« Reply #1 on: April 19, 2011, 08:20:51 AM »
Hi John,

These functions are in Windows "kernell32.dll".
LoadLibraryA / LoadLibraryW (for unicode)
FreeLibrary
GetProcAddress

libhandle= LoadLibrary("mylib.dll")
myfuncAddress=GetProcAddress libhandle, "myfunction")

... when finished:
FreeLibrary libhandle

So calling a library function by name is quite simple in principle. But getting the parameters into the right format can be tricky for an intepreter when there are structures to pass or return

Charles
« Last Edit: May 07, 2011, 07:57:58 PM by o2admin »

JRS

  • Guest
ScriptBasic O2h Embedding
« Reply #2 on: May 05, 2011, 04:30:01 PM »
I now have my version of GTK-Server (FFI scriptable API interface) working on both 32 & 64 bit versions of Ubuntu. I have shown scripting SQLite3 and embedding ScriptBasic within itself. The VARPTR function that was added to GTK-Server opened up a whole new level of API scripting from an interpretive environment I didn't have before. I can even reassign SB variables to contain pointers to structures and strings that are crucial to allow me to script these API's at runtime.

I'm trying to come up with a SB module of API helper functions that make it easier to access type structure and segments of memory (strings) with a simple SB function call. I feel I'm very close to allowing SB to allow full runtime scripting of sharable APIs.

I would really like to revisit your efforts with Windows version of ScriptBasic and implementing O2h as an extension module. You have already shown a POC using the DYC SB extension module so we know it works.
« Last Edit: May 07, 2011, 07:55:18 PM by o2admin »

Charles Pegge

  • Guest
ScriptBasic O2h Embedding
« Reply #3 on: May 06, 2011, 05:52:14 AM »
Hi John,

First we will need to deconstruct those module compile macros. Are they stable and likely to remain so?

But for many tasks you can use Oxygen to spit DLLs for ScriptBasic to use with DYC. With the RTL32 runtime library, these DLLs could be made independent of Oxygen itself.

Do you have any specific applications in mind?

Charles
« Last Edit: May 07, 2011, 07:56:40 PM by o2admin »

JRS

  • Guest
ScriptBasic O2h Embedding
« Reply #4 on: May 06, 2011, 08:29:29 AM »
Charles,

The goal is to create a O2h extension module for ScriptBasic (like thinBasic) that would allow the programmer to run O2h scripts that can be called from SB. If I understand correctly, O2h is a DLL API that I can call and there really isn't anything you need to do on your end, correct?

John
« Last Edit: May 07, 2011, 07:55:56 PM by o2admin »

Charles Pegge

  • Guest
ScriptBasic O2h Embedding
« Reply #5 on: May 06, 2011, 12:14:17 PM »
John,

To create a true module, I would need to create an SBOxygen.dll like thinBasic_Oxygen.dll.

It can also be run as it is through DYC but due to the limitations of DYC Oxygen requires a mediating helper DLL which I named SBO2. This approach will give you plenty of flexibility but lacks the full integration of a  standard SB module.

demo2.sb (ScriptBasic)
Code: [Select]
'---------------------------------
'USING SBO2 WITH SCRIPTBASIC DYC
'---------------------------------

'ScriptBasic

module dyc
  declare sub     ::dyc alias "dyc" lib "dyc"
end module



'OXYGEN SOURCE CODE
'------------------

send="""

  print "Greetings from Embedded Compiled Oxygen Program"

""" & chr$(0)

bufferlength=1000
receive=space(bufferlength)

replylength=dyc::dyc("ms,i,sbo2.dll,run,ZZL",send,receive,bufferlength)
'print replylength
print left(receive,replylength)
line input w


SBO2.DLL
Code: [Select]
 'COMPILING WITH INDEPENDENT RUN TIME LIBRARY


  #file "sbo2.dll" 'COMPILING WITH OXYGEN'S RUN TIME LIBRARY
  library "oxygen.dll"

  declare sub      o2_asmo  (byval s as string)
  declare sub      o2_basic (byval s as string)
  declare function o2_buf   (byval n as long) as long
  declare function o2_errno () as long
  declare function o2_error () as string
  declare function o2_exec  (optional byval p as long) as long
  declare function o2_get   () as string
  declare function o2_len   () as long
  declare function o2_prep  (byval srcBSTR as string) as string
  declare sub      o2_put   (byval c as string)
  declare function o2_view  (byval srcBSTR as string) as string

  library ""



  '----------------------------------------------------------------------
  function message(sys send, sys receive, sys bufferlength) as sys export
  '======================================================================
  '
  zstring * z : &z=send
  print z
  '
  s="Greetings from sbo2 oxygen!"
  replylength=len s
  if replylength>bufferlength then replylength=bufferlength
  copy receive, *s, replylength
  return replylength
  end function



  '------------------------------------------------------------------
  function run(sys send, sys receive, sys bufferlength) as sys export
  '==================================================================
  '
  zstring * z : &z=send
  string c=z
  string s=""
  o2_asmo c
  if o2_errno then
    s=o2_error
  else
    o2_exec
    s="Okay"
  end if
  '
  replylength=len s
  if replylength>bufferlength then replylength=bufferlength
  copy receive, *s, replylength
  return replylength
  end function

Charles
« Last Edit: May 07, 2011, 07:56:25 PM by o2admin »

JRS

  • Guest
ScriptBasic O2h Embedding
« Reply #6 on: May 06, 2011, 10:14:39 PM »
Charles,

I could use GTK-Server as my FFI  rather than DYC. If scripting the O2h API becomes too difficult, I would wrap the O2h DLL as an extension module giving O2h and SB a C environment to communicate providing a high level interface to SB.

Where would be the best place to start to understand the O2h API and it's interface requirements?

I read the intro to O2h and it said that I can pass it a source string and O2h will return a .exe or .dll of the script. I'm not sure I understand how this is considered embedded. Couldn't I have done that from the command line? Can you explain what you mean by embedding O2h?

Update

I just discovered the SB02 directory in the O2h distribution. Thanks for all the hard work with this. I'm going to try and get my arms around what you have already done and and see if I can enhance the interface a bit.

BTW, SBembed1 works great under Wine.



Code: Text
  1. '
  2. ' SCRIPTBASIC
  3. '
  4. ' ----------------
  5. ' GLOBAL VARIABLES
  6. ' ================
  7.  
  8. a=42
  9. b=sqr(2)
  10. s="hello world!"
  11.  
  12. ' ---------
  13. ' FUNCTIONS
  14. ' =========
  15.  
  16. function dprint
  17.   sp="  "
  18.   cr="\n"
  19.   tab=chr$(9)
  20. end function
  21.  
  22. function eprint(a,b,c,d)
  23.   eprint="ans " & a+b+c+d
  24. end function
  25.  

Code: Text
  1.   '#file "SBembed1.exe"
  2.  
  3.   include "scriba.inc"
  4.   indexbase 0
  5.  
  6.   dim as long pProgram,iError,cArgs
  7.   dim as long f1,f2,v
  8.   dim as long n,m
  9.   dim as SbData ReturnData,ArgData(3)
  10.   dim as sbdata byref pdat
  11.   dim as long qdat
  12.  
  13.   cr=chr(13)+chr(10)
  14.  
  15.   pr="Embedded ScriptBasic Tests" cr cr
  16.  
  17.   function newmem CDECL (ByVal le As Long) As BSTR Export
  18.     return nuls le
  19.   end function
  20.  
  21.   sub freemem CDECL (ByVal p As bstr) Export
  22.     frees p
  23.   end sub
  24.  
  25.   'SetConsoleTitle "FreeBasic ScriptBasic Embedding Test"
  26.  
  27.   'LOADING AND RUNNING A PROGRAM
  28.   '-----------------------------
  29.  
  30.   pProgram=scriba_new (& newmem, & freemem)
  31.   'scriba_LoadConfiguration(pProgram,"c:\scriptbasic\bin\scriba.conf")
  32.  
  33.   finit 'reinitialise FPU
  34.  
  35.   scriba_SetFileName(pProgram,"SBProg1.bas")
  36.  
  37.   iError=scriba_LoadSourceProgram(pProgram)
  38.   if iError then goto ending
  39.   iError=scriba_Run(pProgram,"Hello")
  40.   if iError then goto ending
  41.  
  42.   'ACCESSING GLOBAL DATA
  43.   '---------------------
  44.  
  45.   v=scriba_LookupVariableByName(pProgram,"main::a")  
  46.   scriba_GetVariable(pProgram,v,& pdat)
  47.   pr+="read A: "str(pdat.lng) cr
  48.   m=pdat.lng+100
  49.   pr+="add 100 to A" cr
  50.   scriba_SetVariable(pProgram,v,2,m,0,"",0)
  51.   scriba_GetVariable(pProgram,v, & pdat)
  52.   pr+="read A: "str(pdat.lng) cr
  53.  
  54.   'CALLING SIMPLE SUBROUTINE
  55.   '-------------------------
  56.  
  57.   f1=scriba_LookupFunctionByName(pProgram,"main::dprint")
  58.   if f1=0 then print "Unable to locat Dprint" : goto ending
  59.   iError=scriba_Call(pProgram,f1)
  60.   if iError then goto ending
  61.  
  62.   'CALLING FUNCTION, RETURNING DATA AND GETTING ALTERED PARAMS
  63.   '-----------------------------------------------------------
  64.  
  65.   f2=scriba_LookupFunctionByName(pProgram,"main::eprint")
  66.   if f2=0 then print "Unable to locate Eprint" : goto ending
  67.  
  68.   'SETUP ARGUMENTS
  69.   '---------------
  70.   'these can be used for both input and output
  71.  
  72.   ArgData(0).typ=SBT_DOUBLE
  73.   ArgData(1).typ=SBT_DOUBLE
  74.   ArgData(2).typ=SBT_DOUBLE
  75.   ArgData(3).typ=SBT_DOUBLE
  76.  
  77.   ArgData(0).siz=0
  78.   ArgData(1).siz=0
  79.   ArgData(2).siz=0
  80.   ArgData(3).siz=0
  81.  
  82.   ArgData(0).dbl=11
  83.   ArgData(1).dbl=12
  84.   ArgData(2).dbl=13
  85.   ArgData(3).dbl=14
  86.  
  87.   cArgs=4
  88.   pr+="call F2:" cr
  89.   iError=scriba_CallArgEx(pProgram, f2, ReturnData, cArgs, ArgData)
  90.   if iError then goto ending
  91.   sys c=ReturnData.typ
  92.  
  93.   'READ RETURNED VALUE
  94.   '-------------------
  95.  
  96.   select case  c
  97.     case SBT_UNDEF  : pr+= "Undefined "
  98.     case SBT_DOUBLE : pr+="double "  ReturnData.dbl
  99.     case SBT_LONG   : pr+="long "    ReturnData.lng
  100.     case SBT_STRING : pr+="zstring " ReturnData.str
  101.     case SBT_ZCHAR  : pr+="zchar "   ReturnData.str
  102.   end select
  103.  
  104.   pr+=cr
  105.   print pr
  106.  
  107.   '------
  108.   ending:
  109.   '======
  110.  
  111.   scriba_destroy(pProgram)
  112.   if iError then print "ERROR:  " + hex(iError)  ' + "  " + hex(pProgram)
  113.  

Both sbo2demo1.sb and sbo2demo2.sb work fine running scriba from the wineconsole.


John
« Last Edit: May 07, 2011, 07:56:56 PM by o2admin »

JRS

  • Guest
ScriptBasic O2h Embedding
« Reply #7 on: May 07, 2011, 03:46:10 PM »
Charles,

It doesn't look like I'm going to be able to get GTK-Server as my FFI (DYC replacement) working under Wine.  :-\

Creating a C or O2h created SB extension module for O2h seems the only way to do this right.

John
« Last Edit: May 07, 2011, 07:57:11 PM by o2admin »

Charles Pegge

  • Guest
ScriptBasic O2h Embedding
« Reply #8 on: May 07, 2011, 06:38:20 PM »
John,

Does DYC perform correctly in Wine?

I'm looking for stepping stones :)

Charles
« Last Edit: May 07, 2011, 07:57:23 PM by o2admin »

JRS

  • Guest
ScriptBasic O2h Embedding
« Reply #9 on: May 07, 2011, 06:48:41 PM »
DYC works great. See the previous post showing your examples of embedding O2h in SB and embedding SB in O2h. I could add the VARPTR  feature into DYC that would allow us to access pointers and reassign SB variables to structures and strings from a pointer reference that would extend the DYC interface and eliminate the need for the helper DLL your using now.

Gtk under Wine is the only issue I have at this time.

« Last Edit: May 07, 2011, 07:57:37 PM by o2admin »

JRS

  • Guest
Re: ScriptBasic O2h Embedding
« Reply #10 on: May 07, 2011, 09:27:28 PM »
I fired up my old disk that had a Windows XP partition and I found an example you did of calling OXYGEN.DLL directly.

Code: [Select]
'---------------------------------
'USING OXYGEN WITH SCRIPTBASIC DYC
'---------------------------------

'ScriptBasic

import dyc.bas


'OXYGEN SOURCE CODE
'------------------

src="""
  print "Greetings from OxygenBasic!"

""" & chr$(0)

dyc::dyc("ms,i,OXYGEN.DLL,o2_mode,L",0)
dyc::dyc("ms,i,OXYGEN.DLL,o2_basic,Z",src)


'how do we make dll calls that have no arguments?
'TRY THIS
e=dyc::dyc("ms,i,OXYGEN.DLL,o2_error,C")
'e=0
if e=0 then
  dyc::dyc("ms,i,OXYGEN.DLL,o2_exec,L",0)
endif

« Last Edit: May 07, 2011, 09:43:04 PM by JRS »

JRS

  • Guest
Re: ScriptBasic O2h Embedding
« Reply #11 on: May 07, 2011, 11:30:35 PM »
Something more than a print statement.

interation.sb
Code: [Select]
declare sub dll alias "dyc" lib "dyc"

src="""
def q 10
single v[q]<=(9,8,7,6,5,4,3)
single tot

for i=1 to q
  tot+=v[i]
next

print "Number: " q "   Total: " v "  Average: " str(v/q)
""" & 0x0
dll("ms,i,OXYGEN.DLL,o2_mode,L",0)
dll("ms,i,OXYGEN.DLL,o2_basic,Z",src)
dll("ms,i,OXYGEN.DLL,o2_exec,L",0)



The threads.o2bas O2h example works from SB.
« Last Edit: May 08, 2011, 12:03:09 AM by JRS »

JRS

  • Guest
Re: ScriptBasic O2h Embedding
« Reply #12 on: May 08, 2011, 12:41:35 AM »
How can I return a response from O2h other than a popup dialog embedded with text?

  declare function o2_get   () as string

Can I call this function to return a response. Can you explain the issue why you had to create a helper DLL to interface with SB?

It would be cool to be able to create a DLL on the fly (docs indicate a .exe or .dll) and use DYC to call it. I'm pretty sure if you use a SB (string) variable as a return to a DYC called function it would return a string SB can use.
« Last Edit: May 08, 2011, 12:50:42 AM by JRS »

Charles Pegge

  • Guest
Re: ScriptBasic O2h Embedding
« Reply #13 on: May 08, 2011, 03:44:45 AM »

Hi John,

Many thanks for your demos.

returning data is exactly the problem. (Apart from nor being able to use o2_error).

I have been working on SBO2.dll to address this task. Returning text data to SB is quite easy. Check out demos 5 & 6 with this version of SBO2 (zipped below)

ScriptBasic
Code: [Select]
declare sub dll alias "dyc" lib "dyc"

'OXYGEN SOURCE CODE
'------------------

prog="""

  tab=chr 9
  crlf=chr(13)+chr(10)
  single  v=(1 2 3 4)*2+1.25
  bstring s="result:" tab str(v) crlf
  mov eax,s 'direct return (the string will be copied back to SB)
 

""" & chr$(0)


bufferlength=1000
receive=space(bufferlength)

replylength=dll("ms,i,sbo2.dll,run,ZZL",prog,receive,bufferlength)
v=0

'print left(receive,replylength)

a=instr(receive,"result:")
if (a>0)and(a<replylength) then
  v=val(mid(receive,a+8,20))
end if

print v*2

line input w

Charles

[attachment deleted by admin]

Charles Pegge

  • Guest
Re: ScriptBasic O2h Embedding
« Reply #14 on: May 08, 2011, 04:06:45 AM »

With regard to creating DLLs on the fly:

This is certainly possible. But I presume SB binds to all of the specified libraries before runtime. If so then you wont be able to use the DLL immediately following creation, within the same SB program.

Charles