Oxygen Basic

Information => Open Forum => Topic started by: JRS on April 18, 2011, 09:24:55 PM

Title: ScriptBasic O2h Embedding
Post by: JRS 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 (http://www.scriptbasic.org/docs/dg/devguide_2.15.html)

John
Title: ScriptBasic O2h Embedding
Post by: Charles Pegge 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
Title: ScriptBasic O2h Embedding
Post by: JRS 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.
Title: ScriptBasic O2h Embedding
Post by: Charles Pegge 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
Title: ScriptBasic O2h Embedding
Post by: JRS 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
Title: ScriptBasic O2h Embedding
Post by: Charles Pegge 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
Title: ScriptBasic O2h Embedding
Post by: JRS 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.

(http://files.allbasic.info/O2/sb_o2h_embed.png)

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
Title: ScriptBasic O2h Embedding
Post by: JRS 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
Title: ScriptBasic O2h Embedding
Post by: Charles Pegge on May 07, 2011, 06:38:20 PM
John,

Does DYC perform correctly in Wine?

I'm looking for stepping stones :)

Charles
Title: ScriptBasic O2h Embedding
Post by: JRS 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.

Title: Re: ScriptBasic O2h Embedding
Post by: JRS 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

(http://files.allbasic.info/ScriptBasic/sbdirect.png)
Title: Re: ScriptBasic O2h Embedding
Post by: JRS 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)

(http://files.allbasic.info/ScriptBasic/sbo2_it.png)

The threads.o2bas O2h example works from SB.
Title: Re: ScriptBasic O2h Embedding
Post by: JRS 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.
Title: Re: ScriptBasic O2h Embedding
Post by: Charles Pegge 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]
Title: Re: ScriptBasic O2h Embedding
Post by: Charles Pegge 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
Title: Re: ScriptBasic O2h Embedding
Post by: JRS on May 08, 2011, 09:13:01 AM
With DYC, you can load and access a DLL at any point during runtime. GTK-Server works in the same way with it's FFI solution. Scripting APIs is the primary goal of ScriptBasic rather than having to use a C compiler to create an extension module that must be loaded before the script runs.

I'll take a look at the examples using the enhanced SBO2.DLL you attached.

Thanks for all your help with this!
Title: Re: ScriptBasic O2h Embedding
Post by: JRS on May 08, 2011, 09:33:03 AM
Here are a couple of examples of using a DYC like FFI using GTK-Server under Linux.

Self embeding of SB.
Code: [Select]
DECLARE SUB DLL ALIAS "_idll" LIB "gtk-server"
DECLARE SUB REQUIRE ALIAS "_idll_require" LIB "gtk-server"
DECLARE SUB DEFINE ALIAS "_idll_define" LIB "gtk-server"

REQUIRE "libiDLL.so"

DEFINE "sb_new NONE POINTER 0"
DEFINE "scriba_LoadConfiguration NONE INT 2 POINTER STRING"
DEFINE "scriba_SetFileName NONE INT 2 POINTER STRING"
DEFINE "scriba_Run NONE INT 2 POINTER STRING"
DEFINE "scriba_LoadSourceProgram NONE INT 1 POINTER"
DEFINE "scriba_destroy NONE NONE 1 POINTER"

pProgram = DLL("sb_new")
DLL("scriba_LoadConfiguration " & pProgram & " \"/etc/scriba/basic.conf\"")
DLL("scriba_SetFileName " & pProgram & " \"E01.sb\"")
DLL("scriba_LoadSourceProgram " & pProgram)
DLL("scriba_Run " & pProgram & " \"JRS\"")
DLL("scriba_destroy " & pProgram)

E01.sb
Code: [Select]
cmd = COMMAND()

PRINT "ARG = ",cmd,"\n"

FOR x = 1 TO 10
  PRINT x,"\n"
NEXT

jrs@Laptop:~/SB/test$ scriba embed.sb
ARG = JRS
1
2
3
4
5
6
7
8
9
10
jrs@Laptop:~/SB/test$


This example is scripting the SQLite3 API dynamically at runtime and using the VARPTR function added to GTK-Server for SB.
Code: [Select]
' SQLite3 Test Script

DECLARE SUB DLL ALIAS "_idll" LIB "gtk-server"
DECLARE SUB REQUIRE ALIAS "_idll_require" LIB "gtk-server"
DECLARE SUB DEFINE ALIAS "_idll_define" LIB "gtk-server"
DECLARE SUB VARPTR ALIAS "varptr" LIB "gtk-server"

REQUIRE "libsqlite3.so"

DEFINE "sqlite3_open NONE INT 2 STRING LONG"
DEFINE "sqlite3_exec NONE INT 5 LONG STRING INT NULL PTR_STRING"
DEFINE "sqlite3_prepare_v2 NONE INT 5 LONG STRING INT PTR_LONG NULL"
DEFINE "sqlite3_step NONE INT 1 LONG"
DEFINE "sqlite3_column_text NONE STRING 2 LONG INT"
DEFINE "sqlite3_close NONE INT 1 LONG"

CONST SQLITE_ROW = 100
db = 0
dberr = 0
stmt = 0

DLL("sqlite3_open \"testsql\" " & VARPTR(db))
errmsg = DLL("sqlite3_exec " & db & " \"CREATE TABLE demo(someval INTEGER,  sometxt TEXT);\" 0 0 " & VARPTR(dberr))
PRINT "DB ERROR: ",errmsg,"\n"
DLL("sqlite3_exec " & db & " \"INSERT INTO demo VALUES (123, 'Hello');\" 0 0 " & VARPTR(dberr))
DLL("sqlite3_exec " & db & " \"INSERT INTO demo VALUES (234, 'cruel');\" 0 0 " & VARPTR(dberr))
DLL("sqlite3_exec " & db & " \"INSERT INTO demo VALUES (345, 'world');\" 0 0 " & VARPTR(dberr))
result = DLL("sqlite3_prepare_v2 " & db & " \"SELECT * FROM demo;\" -1 " & VARPTR(stmt) & " 0")
SPLIT result BY " " TO ok, stmt

WHILE DLL("sqlite3_step " & stmt) = SQLITE_ROW
  PRINT DLL("sqlite3_column_text " & stmt & " " & 0) & " - " & DLL("sqlite3_column_text " & stmt & " " & 1),"\n"
WEND

DLL("sqlite3_close " & db)

jrs@laptop:~/sb/test$ scriba sqlite3.sb
DB ERROR: 0 (null)
123 - Hello
234 - cruel
345 - world
jrs@laptop:~/sb/test$
Title: Re: ScriptBasic O2h Embedding
Post by: JRS on May 08, 2011, 09:26:20 PM
Charles,

Here is the sbo2demo6.sb redone a bit.

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

'OXYGEN SOURCE CODE
'------------------
prog="""

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

bufferlength = 1000
receive = space(bufferlength)

dll "ms,i,sbo2.dll,run,ZZL", prog, receive, bufferlength

split receive by "\t" to s1, s2, s3
print trim(receive),"\n"
print format("%6.4f",s2),"\n"

C:\o2h\A32\examples\SBO2>scriba sbo2-6.sb
result: 21.25
21.2500

C:\o2h\A32\examples\SBO2>

I just downloaded A33 and tried the above. I had use the sbo2.dll you recently posted to get it to work.

C:\o2h\a33\examples\SBO2>scriba sbo2-6.sb
result: 21.25
21.2500

C:\o2h\a33\examples\SBO2>
Title: Re: ScriptBasic O2h Embedding
Post by: JRS on May 09, 2011, 02:00:44 AM
The following is the code Armando gave me to add VARPTR to GTK-Server so I could use SB variables as placeholders for pointers I may need to pass. I even created a STRPTR function in SB with a combination of VARPTR and calling the C API strcpy() via GTK-Server.

Code: [Select]
besFUNCTION(varptr)
  VARIABLE ptr;

  if(besARGNR>1) return EX_ERROR_TOO_MANY_ARGUMENTS;
  if(besARGNR<1) return EX_ERROR_TOO_FEW_ARGUMENTS;

  besALLOC_RETURN_LONG
  
  ptr = besARGUMENT(1);
  besDEREFERENCE(ptr);
  
  LONGVALUE(besRETURNVALUE) = (int)ptr;

besEND

You should be able to drop this into DYC verbatim to give it a VARPTR function. Can you add the couple extra functions SB requires to sbo2.dll to become an extension module so you have full access to the SB API? Passing buffers then becomes unnecessary. You would be able to control all of SB's variables and other aspects from O2h.

Title: Re: ScriptBasic O2h Embedding
Post by: Charles Pegge on May 09, 2011, 08:39:53 AM
John,

Based on your mods to Demo 6, the next step is to create a persistent program from SB and be able to call its functions at any time from the SB application.

'COMPILE --> ERROR CHECK --> STARTUP --> FUNCTION CALLS --> STOP


This example also demonstrates direct coupling (by pointer) to the send buffer and also the receive buffer:


dll ("ms,i,sbo2.dll,callfun,LzZL", mainfun, send, receive, bufferlength)



Code: [Select]

'--------------------------------------
'WORKING WITH A PERSISTENT O2H PROGRAME
'--------------------------------------


declare sub dll alias "dyc" lib "dyc"

'OXYGEN SOURCE CODE
'
prog="""

  function main(zstring * SBSends, zstring * SBReceives, sys bufferlength) as sys external
    'print SBsends
    string tab=chr 9, cr=chr(13)+chr(10)
    single v=(1 2 3 4)*2+1.25
    SBReceives = SBSends cr "O2H responds" tab str(v) tab chr(0)
  end function

  map[1]= & main


""" & chr(0)

mainfun=1
send="SB Sends a message" & chr(0)
bufferlength = 1000
receive = space(bufferlength)

'COMPILE --> ERROR CHECK --> STARTUP --> FUNCTION CALLS --> STOP

compilerrl= dll( "ms,i,sbo2.dll,compile,ZZL", prog, receive, bufferlength)
if compilerrl>0 then
  print left(receive,compilerrl)
else
  dll ("ms,i,sbo2.dll,start,L",0)
  dll ("ms,i,sbo2.dll,callfun,LzZL", mainfun, send, receive, bufferlength)
  '
  split receive by "\t" to s1, s2, s3
  print s1,"\n"
  print format("%6.4f",s2),"\n"
  '
  dll ("ms,i,sbo2.dll,stop,L", 0)
end if


line input w

Charles

[attachment deleted by admin]
Title: Re: ScriptBasic O2h Embedding
Post by: JRS on May 09, 2011, 10:04:27 AM
That is cool to see an exported function being called on-the-fly. I'm assuming this is all done in memory and a DLL isn't written to disk?

I think Peter did a great job with GTK-Server. I have been slowly gutting the interface to remove everything not SB and FFI specific. (TCP, FIFO, standalone exe, xForms, ...) I'm calling the new version iDLL (interpretive Dynamic Linking Library) The current GTK-Server for Windows Peter pre-compiled doesn't seem to work under Wine but works under Native Windows. (only tried XP) The DYC interface is very close and I always wondered if Peter used it as a POC for GTK-Server.

Is the next step turning SBO2.dll into a SB extension module so you have full access to the SB API?

Title: Re: ScriptBasic O2h Embedding
Post by: Charles Pegge on May 09, 2011, 11:11:07 AM
Not yet John. The next step is to test with a threaded Window which will spin its own message loop independently and leave SB to interact with it asynchronously.

Charles
Title: Re: ScriptBasic O2h Embedding
Post by: JRS on May 09, 2011, 05:44:06 PM
Charles,

I thought I would give GTK-Server under Windows XP a try and can't seem to get the O2h print text to show up in the dialog. What does #qNAN mean?

Code: [Select]
declare sub dll alias "_gtk" lib "gtk-server"

dll("gtk_server_require oxygen.dll")
dll("gtk_server_define o2_mode NONE NONE 1 LONG")
dll("gtk_server_define o2_asmo NONE NONE 1 STRING")
dll("gtk_server_define o2_basic NONE NONE 1 STRING")
dll("gtk_server_define o2_buf NONE LONG 1 LONG")
dll("gtk_server_define o2_errno NONE LONG 0")
dll("gtk_server_define o2_error NONE PTR_STRING 0")
dll("gtk_server_define o2_exec NONE LONG 1 LONG")
dll("gtk_server_define o2_get NONE STRING 0")
dll("gtk_server_define o2_len NONE LONG 0")
dll("gtk_server_define o2_prep NONE STRING 1 STRING")
dll("gtk_server_define o2_put NONE NONE 1 STRING")
dll("gtk_server_define o2_view NONE STRING 1 STRING")

o2src = """

print "Hello from OxygenBasic!"
""" & 0x0

dll("o2_mode 0")
dll("o2_basic " & o2src)
dll("o2_exec 0")

end

(http://files.allbasic.info/ScriptBasic/o2gtksrv.png)

FWIW I put a o2_errno function call after the o2_basic and o2_exec and they both returned zero.

Code: [Select]
o2src = """

a$ = "Hello from OxygenBasic!"
print a$
""" & 0x0

This causes an exception error with Windows.
Title: Re: ScriptBasic O2h Embedding
Post by: Charles Pegge on May 09, 2011, 10:10:46 PM
Hi John,

Could you try terminating the source code string with  & chr(0) instead of & 0x0.

I found SB did not concatenate a null so the compiler was overrunning source code strings.

qNAN is a message from the FPU saying that the value it has been given is Not A Number. 'q' means quiet. This indicates corrupt data at runtime.

May I have a copy of your GTK_server module for testing? My developer SB does not have it.

Charles

PS: o2_error and o2_errno (and o2_len) do not take parameters, hence the crash!

Title: Re: ScriptBasic O2h Embedding
Post by: JRS on May 09, 2011, 11:34:53 PM
That didn't work either. I even tried it without a null and get the same message.

You can get GTK-Server from Peter's site.

http://www.gtk-server.org

Within the modules -> ScriptBasic folder, you will notice gtk-server.dll (goes in your modules SB directory) and the gtk.bas (goes in your SB include but I don't use this file)

Quote
PS: o2_error and o2_errno (and o2_len) do not take parameters, hence the crash!

These functions were defined without a argument.

dll("gtk_server_define o2_errno NONE LONG 0")
dll("gtk_server_define o2_error NONE PTR_STRING 0")
dll("gtk_server_define o2_len NONE LONG 0")

The first parameter after the function name is the callback, (not used) next is the return type, then the number of arguments. (zero in the case of these three functions) The PTR_STRING is a special type that returns the string contents instead if the pointer for it.

This document should help explain the definition options.  gtk-server.cfg (http://www.gtk-server.org/gtk-server.cfg.1.html)

Update

o2src = "print chr(50)"

dll("o2_basic \"" & o2src & "\"")

This prints a 2 which is what I would expect. GTK-Server uses the S-LANG syntax and a space separates the parameters. It can get tricky when an argument has embedded spaces.

o2src = """
print chr(74) chr(82) chr(83)
"""

This prints JRS

I can't get it to work with any embedded " characters. I don't know if this is a GTK-Server or OXYGEN.DLL issue.
Title: Re: ScriptBasic O2h Embedding
Post by: Charles Pegge on May 10, 2011, 03:40:43 AM

John,

Got the GTK server and module in place

I can get it to run. (I can deliberately crash it with Assembler) but I can't get it to display a message on my system. Very odd.

I don't think GTK offers any advantage over DYC anyway. We still need an SBO2.

Charles
Title: Re: ScriptBasic O2h Embedding
Post by: JRS on May 10, 2011, 08:34:14 AM
It was worth a try. Support the Gtk under Windows is fading and Peter isn't doing any further development with GTK-Server now that he has BaCon. Thanks for having s look at it.

Title: Re: ScriptBasic O2h Embedding
Post by: Charles Pegge on May 10, 2011, 09:58:05 AM

The Gtk module is large! (250k+)

Anyway I've now got a threaded window running nicely from SB and also more flexible parameter passing with an extra function in SBO2:

This is how it could be used:

SB code
Code: [Select]
   dll ("ms,i,sbo2.dll,callflex,LLLL", SetPosition,2,x,y)
   dll ("ms,i,sbo2.dll,callflex,LLLLZ", SetText,3,x,y,"Hello!")

Charles
Title: Re: ScriptBasic O2h Embedding
Post by: JRS on May 10, 2011, 11:29:20 AM
Sweet!

I have to agree that Gtk for Windows is a losing battle. Qt is the only hope for a cross platform solution and with Microsoft partnering with Nokia on the mobile end, this may be an easier task moving forward.

Quote
The Gtk module is large! (250k+)

DYC is 200K less.  :)

I can see using O2 as a replacement for the scriba C wrapper that was used as an example for the embeddable SBAPI. This would make the Windows version much more attractive with a GUI IDE/Designer/Debugger instead of just an easy to use console scripting language. This would also remove any limitations and give SB a JIT compiler option for those processor intensive tasks.

O2 embeds SB which embeds O2 for GUI, JIT compiling, OpenGL and more.

I will start testing as soon as you are ready to release a new SBO2.dll to work with.


Title: Re: ScriptBasic O2h Embedding
Post by: Charles Pegge on May 12, 2011, 01:21:08 AM

Hi John,

I now have a threaded window working under SB with a simple protocol for passing messages between SB and the Window thread. But I have put some of the components into the inc/ folder so I think the best thing to do is issue a new Oxygen release with all the pieces in the right place.

I have also made some headway - boring my way into the ScriptBasic internals. and deconstructing the macros. The interface is heavily pointered but I don't need many calls to implement an O2 extension module, so I will extract only what is needed from the headers.

Charles
Title: Re: ScriptBasic O2h Embedding
Post by: JRS on May 12, 2011, 06:18:35 AM
Charles,

That is excellent news!

I'm glad the SB ext. mod. is taking shape as well.

John
Title: Re: ScriptBasic O2h Embedding
Post by: JRS on May 12, 2011, 11:58:07 PM
A while ago, I was trying to use BCX to create an extension module rather than use C. (traditional method) Armando gave me a hand and posted this.

Quote from: AIR
John, here's the problem:

Those macros (besSub/besFunction/besVERSION_NEGOTIATE) are actually function/sub aliases.

You would be better off in the long run taking the time to translate those manually into BCX function/sub syntax.

The one for besVERSION_NEGOTIATE is an interesting one, because it aliases this when using g++:
Code: C
  1. int extern "C" versmodu(int Version, char *pszVariation, void **ppModuleInternal){

I believe what is causing the error you listed above is the order of int extern "C".  I think it should be extern "C" int

Before you say "but SB compiles fine from the makefiles" remember that SB uses gcc under non-windows environments, so the extern "C" decorator is not applied. MBC and BCXU use g++.

Another option is fixing this in the header files themselves.  Flip the order of any macro that has <variable-type> DLL_EXPORT to DLL_EXPORT <variable-type> and the errors go away....

For example, with besVERSION_NEGOTIATE:

THIS
Code: [Select]
#define besVERSION_NEGOTIATE int DLL_EXPORT versmodu(int Version, char *pszVariation, void **ppModuleInternal){
BECOMES THIS:
Code: [Select]
#define besVERSION_NEGOTIATE DLL_EXPORT int versmodu(int Version, char *pszVariation, void **ppModuleInternal){
BTW, besVERSION_NEGOTIATE translated to BCX becomes:
Code: Text
  1. function versmodu(Version as integer, pszVariation as string, ppModuleInternal as void ptr ptr) as integer export

So it's not really that difficult.  You wouldn't be converting ALL of the macros, just the ones that pertain to function/sub aliases....

I then used Peter Verhas's trial example extension module code to create a BCX version.

Code: [Select]
$DLL
$EXECON "-I/usr/src/scriptbasic"
 
#include <basext.h>

'besVERSION_NEGOTIATE
FUNCTION versmodu(Version as integer, pszVariation as string, ppModuleInternal as void ptr ptr) as integer export
  FUNCTION = INTERFACE_VERSION
END FUNCTION

'besSUB_START
FUNCTION bootmodu(pSt as pSupportTable, ppModuleInternal as void ptr ptr, pParameters as pFixSizeMemoryObject, pReturnValue as pFixSizeMemoryObject ptr) as integer export
  DIM pEo AS pExecuteObject
  DIM pL AS long ptr
  besMODULEPOINTER = besALLOC(sizeof(long))
  IF besMODULEPOINTER = NULL THEN FUNCTION = 0
  pL = (long *)besMODULEPOINTER
  *pL = 0
  FUNCTION = 0
END FUNCTION
 
'besSUB_FINISH
FUNCTION finimodu(pSt as pSupportTable, ppModuleInternal as void ptr ptr, pParameters as pFixSizeMemoryObject, pReturnValue as pFixSizeMemoryObject ptr) as integer export
  DIM pEo AS pExecuteObject
  FUNCTION = 0
END FUNCTION

'besFUNCTION
FUNCTION trial(pSt as pSupportTable, ppModuleInternal as void ptr ptr, pParameters as pFixSizeMemoryObject, pReturnValue as pFixSizeMemoryObject ptr) as integer export

  DIM pEo AS pExecuteObject
  DIM pL AS long ptr

  PRINT "Function trial was started..."
  pL = (long *)besMODULEPOINTER
  (*pL)++
  besRETURNVALUE = besNEWMORTALLONG
  LONGVALUE(besRETURNVALUE) = *pL
 
  PRINT "Module directory is ";(char*)besCONFIG("module")
  PRINT "dll extension is ";(char*)besCONFIG("dll")
  PRINT "include directory is ";(char*)besCONFIG("include")

  FUNCTION = 0
END FUNCTION

Title: Re: ScriptBasic O2h Embedding
Post by: Charles Pegge on May 13, 2011, 02:49:52 PM

Hi John,

I've now got the module interface working. I found Assembler was the easiest way to do it. This is my workbench code for testing various data types.

Because it is not using the macros and a C compiler, we have to trust in the stability of the data structures and function tables across different builds.

Do you normally recompile all the extension modules when the core SB is recompiled?

Code: [Select]
'extension module for ScriptBasic:

  '23:02 11/05/2011
  '23:31 13/05/2011
  '
  'Charles Pegge

  #file "mdlt.dll"


  '----------------------------------------------------------------------------------
  function versmodu cdecl (sys Version, pszVariation, ppModuleInternal) as sys export
  '==================================================================================
  'print "Version: " hex version
  return Version
  end function


  '-------------------------------------------------------------------------------------------
  function bootmodu cdecl (sys pSt, ppModuleInternal, pParameters, pReturnValue) as sys export
  '===========================================================================================
  'print "Boot!"
  end function



  '------------------------------------------------------------------------------------
  function finimodu cdecl (sys pSt, ppModuleInternal, pParameters, pReturnValue) as sys export
  '====================================================================================
  'print "Finish!"
  end function




  '----------------------------------------------------------------------------------------
  function trial cdecl (sys pSt, ppModuleInternal, pParameters, pReturnValue) as sys export
  '========================================================================================
  sys p,t,v,w,pm,pn
  string s
  '
  if pParameters=0 then
    print "no params"
  else
    '
    'HOW MANY ARGUMENTS GIVEN
    '------------------------
    '
    mov ecx,pparameters
    mov eax,[ecx+8] : shr eax,2 : mov w,eax
    'mov eax,[ecx+12] : mov t,al
    '
    'print "No of Arguments given: " w
    '
    'SELECT PARAM pn
    '---------------
    '
    'pParameters->Value.aValue[(X)-1]
    '
    pn=1
    '
    mov ecx,pparameters
    mov ecx,[ecx] 'array of param pointers
    mov eax,pn : dec eax : shl eax,2
    mov ecx,[ecx+eax] 'array offset to get pparam
    '
    mov pm,ecx
    '
    'CONVERSION TO STRING
    '--------------------
    '
    'to string f4 / to long f8 / to double fc
    'pSt->Convert2String(pSt->pEo,(x),pSt->pEo->pGlobalMortalList)
    '
    mov ecx,pSt : mov eax,[ecx] : push [eax+0x8c] : push pm : push eax : call [ecx+0xf4]
    mov ecx,eax
    mov p,ecx
    zstring* z : &z=*p
    '
    'print "As String:  " z
    '
    mov ecx,pSt : mov eax,[ecx] : push [eax+0x8c] : push pm : push eax : call [ecx+0xf8]
    mov ecx,[eax]
    mov p,ecx
    '
    'print "As Long:  " p
    '
    mov ecx,pSt : mov eax,[ecx] : push [eax+0x8c] : push pm : push eax : call [ecx+0xfc]
    mov ecx,eax
    mov p,ecx
    double*d : &d=p
    '
    print "As Double:  " d
    '
    'GET VALUE / STRING POINTER
    '--------------------------
    '
    'mov eax,[ecx]    : mov p,eax  'value / pointer
    'mov eax,[ecx+8]  : mov w,eax  'size
    'mov eax,[ecx+12] : and eax,-1 : mov t,eax
    '
    'type codes 0 undef 1 double 2 long 3 zstring* 4 zchar ff ptr
    '
  end if
  '
  '
  '============
  'RETURN VALUE
  '============
  '
  '
  'check stack:
  'mov w,esp
  '
  '
  ' 00c string  010 long  018 double
  '---------------------------------
  '
  '
  'RETURN LONG
  '-----------
  '
  'long v=456
  '
  'mov ecx,pst : mov eax,[ecx] : push [eax+0x8c] : push [eax+0x94] : call [ecx+0x10]
  'mov ecx,pReturnValue : mov [ecx],eax : mov edx,v : mov [eax],edx
  '
  '
  'RETURN DOUBLE
  '-------------
  '
  'double d=1234.5678
  '
  'mov ecx,pst : mov eax,[ecx] : push [eax+0x8c] : push [eax+0x94] : call [ecx+0x18]
  'mov ecx,pReturnValue : mov [ecx],eax : fld qword d : fstp qword [eax]
  '
  '
  'RETURN STRING
  '-------------
  '
  long ls=8 'length excluding null terminators
  zstring z at p
  '
  mov ecx,pst : mov eax,[ecx] : push [eax+0x8c] : push ls : push [eax+0x94] : call [ecx+0x0c]
  mov ecx,pReturnValue : mov [ecx],eax : mov eax,[eax] : mov p,eax
  z="ABCDEFGH" 'direct input
  '
  '
  'NB: beware cdecl cleanup.
  '-------------------------
  '
  'sub w,esp
  'print "check stack: " hex w
  '
  end function



Charles
Title: Re: ScriptBasic O2h Embedding
Post by: JRS on May 13, 2011, 05:02:39 PM
ASM is the ultimate glue language. I don't think you will find an assembly level programmer that will say it can't be done.

ScriptBasic is unique in that it builds everything from scratch from the source when you run setup. (.h, syntax tables, help, ...) A custom configure program might be the best way to explain it. On the Linux side, Armando built a standard makefile to compile the source without the rebuild.

SB Makefile (http://files.allbasic.info/ScriptBasic/Makefile.txt)

You can build a module using the setup --module=O2 or just run the make for the module in it's extension directory.
Title: Re: ScriptBasic O2h Embedding
Post by: JRS on May 13, 2011, 06:00:38 PM
I compiled your framework SB extension module and this is what it returned for me. (Ubuntu 11.04 64 bit - Wine 1.3)

Code: [Select]
declare sub trial alias "trial" lib "mdlt"

rtn = trial(1)
PRINT rtn,"\n"

rtn = trial(1.1)
PRINT rtn,"\n"

rtn = trial("One")
PRINT rtn,"\n"

The following O2 print dialogs are in the order they occurred.

(http://files.allbasic.info/ScriptBasic/SBO2_1.png)

(http://files.allbasic.info/ScriptBasic/SBO2_2.png)

(http://files.allbasic.info/ScriptBasic/SBO2_3.png)


Code: [Select]
C:\o2h\a33\examples\SBO2>scriba trial.sb
ABCDEFGH
ABCDEFGH
ABCDEFGH

C:\o2h\a33\examples\SBO2>
Title: Re: ScriptBasic O2h Embedding
Post by: JRS on May 14, 2011, 09:08:31 AM
Charles,

After working with your O2 extension module framework for SB, I realized that what you posted is a test suite rather than a O2 version to the trial example Peter Verhas did to help developers understand how to create an extension module.

This example shows passing the variable types SB supports. (long, double and strings) I only saw one commented line of code that looks like you were creating a new SB variable within O2. I don't want to side track you from the GUI work your doing with a O2 thread. When you are ready, I think a SQLite3 extension module in O2 may be a worth while project that would fill a void.

John
Title: Re: ScriptBasic O2h Embedding
Post by: Charles Pegge on May 14, 2011, 12:33:22 PM

Yes John I started with 'trial' and morphed into a set of i/o tests. I found a small misalignment of function table offsets -1 slot less than I thought it should be according to the headers. So I initially got longs instead of string parameters. I also found that all the calls were cdecl, not stdcall, even though we are in an ms environment.

I also looked at the possibility of passing variables Byref but apart from zStrings I have not seen any provision for it, not in the macros anyway.

Otherwise a smooth ride so far :)

Charles
Title: Re: ScriptBasic O2h Embedding
Post by: JRS on May 14, 2011, 01:22:30 PM
You may want to look at Peter's MyAlloc (http://peter.verhas.com/progs/c/scriptbasic/myalloc.html) library. It is used in SB and makes memory/string management easier to work with especially in a multi-threaded environment. Peter is a talented programmer that developed an amazing Basic Scripting API that is like a Christmas present I still haven't finish unwrapping.

Quote from: SB Dev Guide - Memory Management (http://www.scriptbasic.org/docs/dg/devguide_2.8.html)
This module is a general purpose memory allocation module, which can be used in any project that needs heavy and sophisticated memory allocation. Originally the module was developed for the ScriptBasic project. Later we used it for Index.hu Rt AdEgine project and multi-thread features were introduced.

Quote
ScriptBasic is fast, it generates a compact internal code, which is interpreted. This internal code occupies a single, continuous memory chunk and is usually saved into a cache file. The cache file is automatically checked by ScriptBasic and thus it compiles the source only when needed.
Title: Re: ScriptBasic O2h Embedding
Post by: JRS on May 14, 2011, 03:47:54 PM
I think SB was initially developed on Linux based on the ANSI/ISO C standard. Looking at the SB source, you can see that WIN32 was patched in afterwards with #define's. I find the history behind calling conventions (http://en.wikipedia.org/wiki/X86_calling_conventions#Caller_clean-up") interesting.

Quote
When compiling for the x64 architecture using Microsoft tools, there is only one calling convention — the one described here, so that stdcall, thiscall, cdecl, fastcall, etc., are now all one and the same.

Can you hear the sound of another door closing?
Title: Re: ScriptBasic O2h Embedding
Post by: Charles Pegge on May 14, 2011, 09:45:44 PM

Its the same for Linux/Mac 64. there is only one standard calling convention but it differs from the MS standard. I'm not so keen on passing floating point params in the XMM registers.

I found an excellent document describing all the standards across different platforms and compilers:

http://www.agner.org/optimize/calling_conventions.pdf

Charles
Title: Re: ScriptBasic O2h Embedding
Post by: JRS on May 14, 2011, 11:58:27 PM
I downloaded the O2 in-process zip and found some new demos. This is the first example of a SBO2 GUI.

sbo2demo9.sb
Code: [Select]

  ' ======================================
  ' WORKING WITH A PERSISTENT O2H PROGRAME
  ' ======================================

  '09:08 13/05/2011

  declare sub dll alias "dyc" lib "dyc"

  ' ==================
  ' OXYGEN SOURCE CODE
  ' ==================
  '
  O2prog="""
  '
  $ THREADED_WINDOW
  '$ PERSISTANT_WINDOW
  include "GraphWin1B.inc"
  '
  '
  function Commune(zstring * SBSends, zstring * SBReceives, sys bufferlength) as sys external
  '------------------------------------------------------------------------------------------
  'print SBsends
  string tab=chr 9, cr=chr(13)+chr(10)
  single v=(1 2 3 4)*2+1.25
  SBReceives= SBSends cr+
  "O2H responds" tab str(v)  tab +
  "Enter x,y coordinates:" cr+
  "or empty line to quit" tab chr(0)
  end function
  '
  '
  function SetPosition(long x, long y) as long external
  '----------------------------------------------------
  'print "x: " x "  y: " y
  while dat
    if active then sleep(0) else return -1
  wend
  dat[11]<=x,y
  dat=1 'signal update
  return active
  end function
  '
  '
  function CloseWindow() as sys external
  '-------------------------------------
  while dat
    if active then sleep(0) else return -1
  wend
  dat=2 'request shutdown
  return active
  end function
  '
  '
  function IsActive() as sys external
  '----------------------------------
  sleep 0
  return active
  end function

  map <= @Commune, @SetPosition, @CloseWindow, @IsActive

  """ & chr(0)


  ' ================
  ' SCRIPTBASIC CODE
  ' ================
 
  'INTERFACE
  '---------

  Commune    =1
  SetPosition=2
  CloseWindow=3
  IsActive   =4
  send="SB Sends a message" & chr(0)
  bufferlength = 1000
  receive = space(bufferlength)

  '---------------------------------------------------------------
  'COMPILE --> ERROR CHECK --> STARTUP --> FUNCTION CALLS --> STOP
  '---------------------------------------------------------------

  'COMPILE
  '-------

  compilerrl= dll( "ms,i,sbo2.dll,compile,ZZL", O2prog, receive, bufferlength)
  '
  'ERROR CHECK
  '-----------
  '
  if compilerrl>0 then
    print left(receive,compilerrl)
    line input w
  else
    '
    'START DEMO
    '----------
    '
    dll ("ms,i,sbo2.dll,start,L",0)
    '
    'TEST TEXT IO COMMUNICATION
    '--------------------------
    '
    dll ("ms,i,sbo2.dll,callfun,LzZL", Commune, send, receive, bufferlength)
    '
    split receive by "\t" to s1, s2, s3
    print s1,"\n"
    print format("%6.4f",s2),"\n"
    print s3,"\n"
    '
    'WAIT TILL WINDOW IS ACTIVE
    '--------------------------
    '
    ra=0
    c=0
    while ra=0
      ra=dll ("ms,i,sbo2.dll,callflex,LL", IsActive,0)
      c+=1
      if c>100 then
        ra=-1
      end if
    wend
    '
    if ra>0 then
      '
      'TEST USER COMMUNICATION WITH WINDOW
      '-----------------------------------
      '
      'enter x and y coords or quit
      '
      w=" "
      re=1
      while (asc(w)>=32) and (re>0)
        line input w
        if len(w)>1 then
          split w by "," to x,y
          re=dll ("ms,i,sbo2.dll,callflex,LLLL", SetPosition,2,x,y)
        end if
      wend
      '
      'CLOSE DOWN WINDOW
      '-----------------
      '
      dll ("ms,i,sbo2.dll,callflex,LL", CloseWindow,0)
      '
    end if
    '
    'STOP THE PERSISTANT PROGRAM
    '---------------------------
    '
    dll ("ms,i,sbo2.dll,stop,L", 0)
    '
  end if

(http://files.allbasic.info/O2/sbo2_windemo_1.png)

(http://files.allbasic.info/O2/sbo2_windemo_2.png)
Title: Re: ScriptBasic O2h Embedding
Post by: JRS on May 16, 2011, 09:51:58 AM
Hi Charles,

I have been playing around with your mdlt.dll test SB extension module. It seems I'm able to pass strings, integers and floating point values. I noticed that you can return a string as well. Are you using the SB memory management API so if SB closes or errors, all memory is release via the SB MyAlloc version of Peter's library? Is the only way to access the SB API from the O2 extension module via ASM?

John
Title: Re: ScriptBasic O2h Embedding
Post by: Charles Pegge on May 16, 2011, 10:48:45 AM

Hi John,

The interface uses the procedures encoded in the macros, and anything created for SB is "mortal". If there is an error. SB will clean up these elements. The Oxygen compiler dll will be released and shut down in an orderly way but the running O2 program may leave some debris behind when terminated prematurely. Since this is all in-process the OS should clear up on termination, but further thought is needed about how to catch any fatal run-time errors.

Assembler is not the only way to access the SB API but it very efficient and does not rely on a full set of headers. I can make it  less cryptic and maybe create a mini header.

Charles

PS: I found my alignment error, so my mapping of the API is now in agreement with the headers.
Title: Re: ScriptBasic O2h Embedding
Post by: JRS on May 16, 2011, 10:52:23 AM
Quote
PS: I found my alignment error, so my mapping of the API is now in agreement with the headers.

Good thing, I would hate to have to send Peter Verhas a pink slip.  ;D
Title: Re: ScriptBasic O2h Embedding
Post by: JRS on May 17, 2011, 12:19:52 PM
Charles,

I'm trying to get an idea where things are with the O2 extension module and the goals you have with it. I think I could create a SQLite3 O2 extension module with what you have now. Can O2 access the SB scripts variables at this time? (integers, strings and arrays)

I would like to get the SQLite example I posted previously by scripting the API translated to an O2 extension module. I want to use the same syntax all database interfaces use at the script level. (MySQL, ODBC, PostgreSQL, ...)


I also understand your working on a Windows GUI threaded task to deal with Windows messages and provide a passive event loop to SB. Will this GUI interface also allow us to create controls and access their methods and properties in a easy to use way at the SB scripting level?

Not to forget why we came to the party, the ability to pass O2 scripts from SB and run as a JIT compiled program/shared object.

John
Title: Re: ScriptBasic O2h Embedding
Post by: Charles Pegge on May 17, 2011, 08:49:35 PM

John,

Tthe next step is to combine SBO2 with the interfacing software of Mdlt and create an SBOxygen module.

Most of Windows GUI programming is best done Oxygen script. and frequently used procedures can be passed down into SBOxygen. So they are precompiled.

My knowledge of SQL is theoretical at best. Could you show me some stock examples of SB using SQL? Do the modules return data in arrays or as splittable text.

I am currently working on '->' pointer notation so that Oxygen can understand C header macros that contain them.

Charles
Title: Re: ScriptBasic O2h Embedding
Post by: JRS on May 17, 2011, 08:58:06 PM
Here (http://www.oxygenbasic.org/forum/index.php?topic=158.msg1042#msg1042) is the post I made on the second page of this thread that shows both SB embedding itself and a SQLite scripted demo. Where I have a problem is understanding how to use the SQLite C header in O2. Once I got that down, the rest should go smoothly.

Is the O2 ext. mod. going o be like DYC but smarter? Or will it be a framework to create SB extension modules without having to use C?
Title: Re: ScriptBasic O2h Embedding
Post by: JRS on May 17, 2011, 10:47:57 PM
Here is what I have come up with. I attached the self contained SQLite3 console shell to use if you need it.

Code: [Select]
' #include <sqlite3.h>

extern stdcall lib "sqlite3.dll"

  int sqlite3_open(
    const char *filename,   /* Database filename (UTF-8) */
    sqlite3 **ppDb          /* OUT: SQLite db handle */
  );
  
  int sqlite3_exec(
    sqlite3*,                                  /* An open database */
    const char *sql,                           /* SQL to be evaluated */
    int (*callback)(void*,int,char**,char**),  /* Callback function */
    void *,                                    /* 1st argument to callback */
    char **errmsg                              /* Error msg written here */
  );
  
  int sqlite3_prepare_v2(
    sqlite3 *db,            /* Database handle */
    const char *zSql,       /* SQL statement, UTF-8 encoded */
    int nByte,              /* Maximum length of zSql in bytes. */
    sqlite3_stmt **ppStmt,  /* OUT: Statement handle */
    const char **pzTail     /* OUT: Pointer to unused portion of zSql */
  );
  
  int sqlite3_step(sqlite3_stmt*);  /* Evaluate the statement */
  
  const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);  /* The "result set" interface */
  
  int sqlite3_close(sqlite3 *);  /* Destructor for the sqlite3 object */

end extern


[attachment deleted by admin]
Title: Re: ScriptBasic O2h Embedding
Post by: Charles Pegge on May 17, 2011, 11:20:13 PM
Thanks John,

That example will help me to understand how SQL is setup and used.

I can produce a simple header based on this information:

http://www.sqlite.org/c_interface.html

I envisage SBOxygen as starting out with Dyc + compiler functionality and developing into a framework by acquiring commonly used functions to lighten the burden for source scripts. Windows GUI coding is cumbersome and a selection of standard GUIs will often suffice in many applications.

Charles

Title: Re: ScriptBasic O2h Embedding
Post by: JRS on May 19, 2011, 01:39:42 PM
I just finished looking over your besNotes.txt file and the #define work looks like a major effort on your part. I would like to try working with the defines if possible. Have you done any preliminary testing of the SB API via these defines?


Title: Re: ScriptBasic O2h Embedding
Post by: Charles Pegge on May 19, 2011, 10:09:21 PM

Hi John,

I've made a few enhancements to Oxygen towards supporting bes macros and other #defines.

Here are the major ones:

Support C Arrow Notation: ->

The arrows can be used interchangeably with dots since Oygen automatically resolves indirection.

Support classical C function tables

Code: [Select]
  typedef struct _tb
  {
  long (*f1)(long*s)
  long (*f2)(long*s)
  long (*f3)(long*s)
  zstring (*s1)(long*s)
  zstring (*s2)(char*s)
   long (*s3)(char**s)
  } tb,*ptb

(C++ style classes makes this notation obsolete.)


Allow #defines inside types and typedefs.



But There is still some more work to do before we can use the bes headers directly.

Charles
Title: Re: ScriptBasic O2h Embedding
Post by: JRS on May 20, 2011, 12:00:43 AM
It looks like your close to being able to deal with ANSI/ISO C structures transparently in O2. This should make working with C libraries effortless.

I'm looking forward to using O2 with SB. I will be even more overjoyed when there is a native O2 for Linux.

Now that you have had time to unravel SB at the developers level, what is your take on Peter Verhas's effort?
Title: Re: ScriptBasic O2h Embedding
Post by: Charles Pegge on May 20, 2011, 11:26:57 AM

John,

I ought to study the Ansi C standard. :)

I have not gone much beyond exploring Peter Verhas' headers. They are well documented though not easy to work through due to the macros. The intensive use of function tables is a kind of OOP though C does not lend itself to clean coding in this paradigm and I am sure that was one good reason to offer the macros:  to make modules readable by hiding the internal complexity.

Charles
Title: Re: ScriptBasic O2h Embedding
Post by: JRS on May 20, 2011, 08:48:08 PM
The macros seem to be a double edge sword. For the extension module builder, the macros are a big time saver. (if using C) I hope the O2 extension generates new interest in SB on the Windows platform.

I think the work you doing for the SB interface has value beyond just this interface. I think its great O2 is more compatible with C resources and everyone will benefit from it.

 
Title: Re: ScriptBasic O2h Embedding
Post by: JRS on May 21, 2011, 11:45:43 PM
Charles,

I'm trying to get the GNU Scientific Library (GSL) (http://www.gnu.org/software/gsl/) working with DYC.

Code: [Select]
DECLARE SUB DLL ALIAS "dyc" LIB "dyc"

dv = DLL("ms,d,libgsl.dll,gsl_sf_bessel_J0,d",5.0)

PRINT dv,"\n"

1.057783e-307

Based on the results compiled native with gcc under Ubuntu 64, the results for this function don't match.

Code: [Select]
#include <stdio.h>
#include <gsl/gsl_sf_bessel.h>

int
main (void)
{
  double x = 5.0;
  double y = gsl_sf_bessel_J0 (x);
  printf ("J0(%g) = %.48e\n", x, y);
  return 0;
}

gcc -Wall intro.c -lgslcblas -lgsl -o intro

J0(5) = -1.775967713143382642471124199801124632358551025391e-01

Any ideas what might be going wrong?

Update

I figured out what was missing.

dv = DLL("ms8,d,libgsl-0.dll,gsl_sf_bessel_J0,d",5.0)

C:\scriptbasic\test>scriba testgsl.sb
-1.7759677131433826e-001
C:\scriptbasic\test>

GSL.zip (http://files.allbasic.info/ScriptBasic/GSL.zip)
Title: Re: ScriptBasic O2h Embedding
Post by: Charles Pegge on May 22, 2011, 02:15:54 AM
Hi John,

A quick look at the DYC source:

Code: [Select]
     case 0: //define the call type
        switch( *pszFormat ){
          case 'm': case 'M': Flags |= DC_MICROSOFT;    break;
          case 'b': case 'B': Flags |= DC_BORLAND;      break;
          case 'c': case 'C': Flags |= DC_CALL_CDECL;   break;
          case 's': case 'S': Flags |= DC_CALL_STD;     break;
          case '4':           Flags |= DC_RETVAL_MATH4; break;
          case '8':           Flags |= DC_RETVAL_MATH8; break;
          case ',' : iParseState++; break;
          }

Code: [Select]
    else if (Flags & DC_RETVAL_MATH8) {
        _asm fstp qword ptr [Res]
    }

This means the float double result is taken from the FPU stack
Charles
Title: Re: ScriptBasic O2h Embedding
Post by: JRS on May 22, 2011, 02:32:55 AM
Quote from: Charles
This means the float double result is taken from the FPU stack

Quote from: DYC Docs
Finally you can specify 4 or 8 to specify that the function is returning a four or eight-byte floating point number. Although this is a kind of return value specification, it is stated here, because this affects the calling convention. These values are returned not in a memory place from the function but rather in the co-processor register and function dyc has to know to fetch them from there rather than expection the function to return a four or eight-byte memory chunk.
Title: Re: ScriptBasic O2h Embedding
Post by: JRS on May 22, 2011, 05:39:09 PM
Charles,

I converted one of the GSL examples to display all the combinations of a number set.

Code: Text
  1. #include <stdio.h>
  2. #include <gsl/gsl_combination.h>
  3.  
  4. int
  5. main (void)
  6. {
  7.   gsl_combination * c;
  8.   size_t i;
  9.  
  10.   printf ("All subsets of {0,1,2,3} by size:\n") ;
  11.   for (i = 0; i <= 4; i++)
  12.     {
  13.       c = gsl_combination_calloc (4, i);
  14.       do
  15.         {
  16.           printf ("{");
  17.           gsl_combination_fprintf (stdout, c, " %u");
  18.           printf (" }\n");
  19.         }
  20.       while (gsl_combination_next (c) == GSL_SUCCESS);
  21.       gsl_combination_free (c);
  22.     }
  23.  
  24.   return 0;
  25. }
  26.  

jrs@laptop:~/C/gsl/doc/examples$ ./combo
All subsets of {0,1,2,3} by size:
{ }
{ 0 }
{ 1 }
{ 2 }
{ 3 }
{ 0 1 }
{ 0 2 }
{ 0 3 }
{ 1 2 }
{ 1 3 }
{ 2 3 }
{ 0 1 2 }
{ 0 1 3 }
{ 0 2 3 }
{ 1 2 3 }
{ 0 1 2 3 }
jrs@laptop:~/C/gsl/doc/examples$

Code: Text
  1. DECLARE SUB DLL ALIAS "dyc" LIB "dyc"
  2.  
  3. CONST GSL_SUCCESS  = 0
  4.  
  5. PRINT "All subsets of {0,1,2,3} by size:\n"
  6.  
  7. FOR i = 0 TO 4
  8.   c = DLL("ms,l,libgsl-0.dll,gsl_combination_calloc,ll", 4, i)
  9.  
  10.   DO
  11.     PRINT "{"
  12.     DLL("ms,i,libgsl-0.dll,gsl_combination_fprintf,llz", 0, c, " %u")
  13.     PRINT " }\n"
  14.   LOOP WHILE DLL("ms,i,libgsl-0.dll,gsl_combination_next,l", c) = GSL_SUCCESS
  15.   DLL("ms,i,libgsl-0.dll,gsl_combination_free,l", c)
  16. NEXT
  17.  

The program gets as far as printing the blank combo before giving an exception error. My guess is I'm not providing a pointer to STDOUT.

Quote
Backtrace:
=>0 0x7ec95669 MSVCRT_fwrite+0x29() in msvcrt (0x0033ecb4)
  1 0x7ec97222 MSVCRT_vfprintf+0x151() in msvcrt (0x0033f524)
  2 0x7ec9774b MSVCRT_fprintf+0x2a() in msvcrt (0x0033f544)
  3 0x6ef53430 gsl_combination_fprintf+0x2f(stream=(nil), c=0x111c10, format="
u") [d:\gslNew\combination/file.c:73] in libgsl-0 (0x0033f574)
  4 0x1000224b in dyc (+0x224a) (0x0033f5c0)
  5 0x10001cd2 in dyc (+0x1cd1) (0x0033f868)
  6 0x00453915 in scriba (+0x53914) (0x0033f8d8)
  7 0x00412e38 in scriba (+0x12e37) (0x0033f8f4)
  8 0x004137cd in scriba (+0x137cc) (0x0033f948)
  9 0x0044de97 in scriba (+0x4de96) (0x0033f978)
  10 0x00412e38 in scriba (+0x12e37) (0x0033f994)
  11 0x00403dc3 in scriba (+0x3dc2) (0x0033f9a8)
  12 0x00402179 in scriba (+0x2178) (0x0033fe50)
  13 0x004557a5 in scriba (+0x557a4) (0x0033fe90)
  14 0x7b85899c call_process_entry+0xb() in kernel32 (0x0033fea8)
  15 0x7b85963f ExitProcess+0xc9e() in kernel32 (0x0033fee8)
  16 0x7bc72e68 call_thread_func+0xb() in ntdll (0x0033fef8)
  17 0x7bc75920 call_thread_entry_point+0x6f() in ntdll (0x0033ffc8)
  18 0x7bc4aa0a call_dll_entry_point+0x629() in ntdll (0x0033ffe8)

Is there a Windows API call I could use to get the pointer to STDOUT? I noticed there isn't a void return type option with DYC. The best place to add VARPTR, STDIN/OUT pointers, alloc/free function pointers and basext.h is DYC until you get the SBOxygen extension module working. Can I use what we have to provide the STDOUT pointer?



John
Title: Re: ScriptBasic O2h Embedding
Post by: Charles Pegge on May 22, 2011, 08:55:03 PM
Hi John,

If you want to call a void or sub then it is safe to set the return type as i.
the value in the EAX register is read and assigned to a mortal integer which can be safely ignored.

DYC needs a few extras. The main problem for Oxygen was calling a function without any parameters.

I've been thinking about the best way to handling parameters that need to be passed byref. I think using '*' notation would be widely understood:
L*D*D*C** etc.

To recover output values an additional function is required:
x=result(1)
y=(result(2) ...

With regard to GSL, I'm not sure what is happening. It can't be STDOUT since manages to display something. It could be the calling convention. If it requires CDECL and you give it STDCALL it will accumulate stuff on the stack and eventually fail after a few calls.

Charles

Title: Re: ScriptBasic O2h Embedding
Post by: JRS on May 22, 2011, 09:03:24 PM
Quote
It can't be STDOUT since manages to display something.

The something is being printed using the SB PRINT statement. The fprintf() function needs a pointer to STDOUT to work.

 
Title: Re: ScriptBasic O2h Embedding
Post by: Charles Pegge on May 22, 2011, 09:49:53 PM
Yes I see.

Here is some console code for OxygenBasic/tools/toolSrc. It shows how to setup simple console i/o.

I think you need to make a call to kernel32.dll

  %STD_OUTPUT_HANDLE = -11
  ConsOut=GetStdHandle (%STD_OUTPUT_HANDLE)

Code: [Select]

  library "KERNEL32.DLL"
  declare FUNCTION AllocConsole    ALIAS "AllocConsole" () AS LONG
  declare FUNCTION GetCommandLine  ALIAS "GetCommandLineA" () AS DWORD
  declare FUNCTION GetStdHandle    ALIAS "GetStdHandle" (BYVAL handle AS DWORD) AS DWORD
  declare FUNCTION WriteConsole    ALIAS "WriteConsoleA" (BYVAL hConsoleOutput AS DWORD, lpBuffer AS ASCIIZ, BYVAL nNumberOfCharsToWrite AS LONG, lpNumberOfCharsWritten AS LONG, BYVAL lpReserved AS LONG) AS LONG
  declare FUNCTION ReadConsole     ALIAS "ReadConsoleA" (BYVAL hConsoleInput AS DWORD, BYVAL lpBuffer AS DWORD, BYVAL nNumberOfCharsToRead AS LONG, lpNumberOfCharsRead AS LONG, pInputControl AS ANY) AS LONG
  declare FUNCTION SetConsoleTitle ALIAS "SetConsoleTitleA" (lpConsoleTitle AS ASCIIZ) AS LONG
  library ""


  %STD_INPUT_HANDLE  = -10
  %STD_OUTPUT_HANDLE = -11
  %STD_ERROR_HANDLE  = -12


  AllocConsole

  dim as long consIn,consOut,consErr

  ConsIn =GetStdHandle (%STD_INPUT_HANDLE)
  ConsOut=GetStdHandle (%STD_OUTPUT_HANDLE)
  ConsErr=GetStdHandle (%STD_ERROR_HANDLE)

  dim as string bufin
  dim as long buflen,bufrit

  dim as string tab,cr,qu

  tab=chr 9
  qu=chr 34
  cr=chr(13)+chr(10)

  bufin=nuls 1000


  SetConsoleTitle "Oxygen PE SPY"

  '---------------------------
  function output(bufout as string)
  '===========================
    buflen=len bufout
    WriteConsole ConsOut,bufout,buflen,bufrit,0
  end function

  '-------------------------------------
  function input(s as string) as string
  '=====================================
    output s
    ReadConsole consin,*bufin,100,bufrit,0
    function=left bufin,bufrit
  end function


  '-------------------------------
  function commandline() as string
  '=============================== 
    dim byref z as zstring 
    &z=GetCommandLine
    function=z
  end function

  '------------------------------------------
  function stripquotes(s as string) as string
  '==========================================
    dim as long a
    a=asc(s,1)
    if a=34 then
      a=instr 2,s,qu
      s=mid s,2,a-2
    end if
    function=s
  end function


Charles
Title: Re: ScriptBasic O2h Embedding
Post by: JRS on May 22, 2011, 10:10:59 PM
That returns 79 which may be the handle but I need the function pointer to STDOUT.

Title: Re: ScriptBasic O2h Embedding
Post by: Charles Pegge on May 22, 2011, 10:35:21 PM
These kernel32.dll calls will get you the address of WriteConsole


a=LoadLibraryA("kernal32.dll")
p=GetProcAddress(a,"WriteConsoleA")


but I don't know whether this is the function printf expects to use

List of console functions:

http://msdn.microsoft.com/en-us/library/ms682073(v=vs.85).aspx

You need to add 'A' to the names where there is a choice of Ansi or 'W' for wide character.


Code: [Select]
 '---------------------------
  function output(bufout as string)
  '===========================
    buflen=len bufout
    WriteConsole ConsOut,bufout,buflen,bufrit,0
  end function

Charles
Title: Re: ScriptBasic O2h Embedding
Post by: JRS on May 22, 2011, 11:04:17 PM
Code: [Select]
DECLARE SUB DLL ALIAS "dyc" LIB "dyc"

CONST GSL_SUCCESS  = 0

a = DLL("ms,l,kernel32.dll,LoadLibrary,z","kernel32.dll")
p = DLL("ms,l,kernel32.dll,GetProcAddress,lz",a,"WriteConsoleA")

PRINT "All subsets of {0,1,2,3} by size:\n"

FOR i = 0 TO 4
  c = DLL("ms,l,libgsl-0.dll,gsl_combination_calloc,ll", 4, i)

  DO
    PRINT "{"
    DLL("ms,i,libgsl-0.dll,gsl_combination_fprintf,llz", p, c, " %u")
    PRINT " }\n"
  LOOP WHILE DLL("ms,i,libgsl-0.dll,gsl_combination_next,l", c) = GSL_SUCCESS
  DLL("ms,i,libgsl-0.dll,gsl_combination_free,l", c)
NEXT

I'm still getting the exception error.   ???
I added a debug print after getting p and it looks like an address.

C:\gsl\test>scriba gslcombo.sb
2072191600

C:\gsl\test>

int gsl_combination_fprintf (FILE * stream, const gsl_combination * c, const char * format)

I wonder if it might be easier for you to get this example working in O2 first rather then me hacking away with DYC.

Quote
UNIX defines 3 predefined streams (in stdio.h):

   stdin,  stdout,  stderr
Title: Re: ScriptBasic O2h Embedding
Post by: Charles Pegge on May 22, 2011, 11:42:16 PM

Hmm.. I did not see Microsoft on the platform list. - an odd omission, and I don't understand why it needs you to tell it anything about the console.

http://www.gnu.org/software/gsl/

Perhaps a C programmer would be able sort the console i/o for you in the source code or compiler options.

Charles

Title: Re: ScriptBasic O2h Embedding
Post by: JRS on May 23, 2011, 12:05:55 AM
The GSL library was compiled using MinGW. I'll take a look how Peter handles STDOUT in SB for Unix & Windows platforms. Maybe that will shed some light and what is needed.

Here is the site I got the libgsl for Windows from.

http://junjie8422.cn/archives/13

It shows how to build the library under Windows and provides a pre-compiled library if you you don't want to do it yourself.


Title: Re: ScriptBasic O2h Embedding
Post by: JRS on May 25, 2011, 06:03:20 PM
Charles,

I created a ScriptBasic Linux 64 bit extension module to wrap the GSL functions. I gave up on GTK-Server to script GSL.

Code: [Select]
/*
   GNU Scientific Library
   Based on GSL 1.15
   Interface By: John Spikowski
*/

#include <stdio.h>
#include "../../basext.h"
#include <gsl/gsl_sf_bessel.h>
      
besVERSION_NEGOTIATE
    return (int)INTERFACE_VERSION;
besEND

besSUB_START
besEND

besSUB_FINISH
besEND

besFUNCTION(sf_bessel_J0)
  VARIABLE Argument;

  Argument = besARGUMENT(1);
  besDEREFERENCE(Argument);

  besRETURN_DOUBLE(gsl_sf_bessel_J0 (DOUBLEVALUE(Argument)));
besEND

Code: [Select]
DECLARE SUB besselJ0 ALIAS "sf_bessel_J0" LIB "gsl"

PRINT FORMAT("J0(%g) = %.48g", 5, besselJ0(5.0)),"\n"

jrs@laptop:~/sb/test/gsl$ scriba bj0.sb
J0(5) = -0.177596771314338264247112419980112463235855102539
jrs@laptop:~/sb/test/gsl$

Peter Verhas had the C programmer in mind when he created the extension module macro API interface.
Title: Re: ScriptBasic O2h Embedding
Post by: Charles Pegge on May 25, 2011, 07:00:04 PM

Hi John,

For Windows/Wine I see there is a ready to use libGSL.dll here

http://gnuwin32.sourceforge.net/packages/gsl.htm

gsl-1.8-bin.zip

I took a peek inside the DLL. The names are free of mangling so it looks simple to use.


Charles
Title: Re: ScriptBasic O2h Embedding
Post by: JRS on May 25, 2011, 08:08:19 PM
The same extension module I'm creating under Linux should compile under Windows as a DLL.

I can now fully appreciate the work you put into cracking the SB macros so they can be called from Oxygen.

Latest GSL version (May 6th, 2011) gsl-1.15.tar.gz (http://gnu.mirrors.pair.com/gnu/gsl/gsl-1.15.tar.gz)

Title: Re: ScriptBasic O2h Embedding
Post by: Charles Pegge on May 26, 2011, 02:31:22 AM

Would an enhanced DYC be worth developing John?

I would not advocate it for building Windows GUIs but for less complex interfacing it could fill the gap.

Charles
Title: Re: ScriptBasic O2h Embedding
Post by: JRS on May 26, 2011, 08:40:35 AM
Quote
Would an enhanced DYC be worth developing John?

I think the ability to script an external library or system API without having to create a extension module is key feature of DYC. A VARPTR() function and ability to access structures given their pointer would be a big plus.

Title: Re: ScriptBasic O2h Embedding
Post by: Charles Pegge on May 26, 2011, 09:09:01 AM

For passing and returning structures, I think we should use the join and split functions and make text the principle form of data transfer.

The structures will need to carry a type-signature just like the parameter signature in a dyc call.

For example, a windows rectangle (rect) would look something like this:

rect1="100,200,640,480,LLLL"

(Placing the signature as the final term will make array indexation to the values a little easier.)

Charles
Title: Re: ScriptBasic O2h Embedding
Post by: JRS on May 26, 2011, 09:31:57 AM
I like it!

I plan on creating an argument validation function for extension modules that check the number of passed arguments and they are of the right type for the called function.

argerr = besArgVal("D")

This function would test to make sure only one argument should be passed and as a number in a floating point format. The function will return a non-zero if invalid arguments are passed and would tell scriba an error occurred.
Title: Re: ScriptBasic O2h Embedding
Post by: JRS on May 27, 2011, 11:02:27 AM
Charles,

I'm trying to add this function to the SB GSL extension module and I'm getting a segment fault when accessing the function.

Code: [Select]
besFUNCTION(_frexp)
  VARIABLE Argument;

  Argument = besARGUMENT(1);
  besDEREFERENCE(Argument);
  double x = DOUBLEVALUE(Argument);
  Argument = besARGUMENT(2);
  besDEREFERENCE(Argument);
  int * y = LONGVALUE(Argument);

  besRETURN_DOUBLE(gsl_frexp(x, y));
besEND

Quote
Function: double gsl_frexp (double x, int * e)

This function splits the number x into its normalized fraction f and exponent e, such that x = f * 2^e and 0.5 <= f < 1. The function returns f and stores the exponent in e. If x is zero, both f and e are set to zero. This function provides an alternative to the standard math function frexp(x, e).

Code: [Select]
DECLARE SUB frexp ALIAS "_frexp" LIB "gsl"

e = 0
PRINT FORMAT("%g",frexp(12.5,e)),"\n"
PRINT e,"\n"

Title: Re: ScriptBasic O2h Embedding
Post by: JRS on May 27, 2011, 12:24:40 PM
I figured it out.

Code: [Select]
besFUNCTION(_frexp)
  VARIABLE Argument;
  LEFTVALUE Lval;
  unsigned long __refcount_;

  Argument = besARGUMENT(1);
  besDEREFERENCE(Argument);
  double x = DOUBLEVALUE(Argument);
  Argument = besARGUMENT(2);
  besLEFTVALUE(Argument,Lval);
  besRELEASE(*Lval);
  *Lval = besNEWLONG;

  besRETURN_DOUBLE(gsl_frexp(x, *Lval));
besEND

Code: [Select]
DECLARE SUB frexp ALIAS "_frexp" LIB "gsl"

x = 16.4
fraction = frexp(x, e)

PRINT FORMAT("%g",fraction),"\n"
PRINT e,"\n"

jrs@laptop:~/sb/test/gsl$ scriba emath.sb
0.5125
5

Quote from: LEFTVALUE
A left value is a special expression that a value can be assigned, and therefore they usually stand on the left side of the assignment operator. That is the reason for the name.

I would have gone with BYREFVALUE instead. The __refcount_ should have been defined in the basext.h file for the LEFTVALUE macro. I can see a bit more macro polishing still needing to be done.
Title: Re: ScriptBasic O2h Embedding
Post by: Charles Pegge on May 28, 2011, 01:28:27 AM

John,

Good to know you cracked it. I would not have much of a clue.

The difficulty is that the macros are a new language to learn. Furthermore macros are not syntax checked to the same degree as the base language. I think it would be easier keeping with the original C and using comments instead of macros. There is also the option of using wrapper functions for the more complex operations.

I found the best way to use macros in Oxygen is to use them very locally. So you can immediately see what they mean as well as how they are used. (Unlike C, Oxygen macros may have local scope. They can 'disappear' when no longer needed and not fill up the global namespace.

Charles
Title: Re: ScriptBasic O2h Embedding
Post by: JRS on May 28, 2011, 09:08:48 AM
Quote
The difficulty is that the macros are a new language to learn.

For me at this point, it's easier to understand macros then the function table pointer access method to the SB API. What got me going in the right direction with assigning the argument was the MySQL extension module (FetchHash) that fills an associative array with the result set given only a variable name as an argument. This example will be helpful once again when I get into the more complex GSL functions that work with packed arrays.

Update: Armando chimed in and took the macros to a new level.

Quote from: AIR
Nice work, John.  I just popped in to see what you've been up to.  

I'm curious if the following would work using some of the higher-level macros.

For example, originally you had:
Code: [Select]
besFUNCTION(_hypot3)
  VARIABLE Argument;

  Argument = besARGUMENT(1);
  besDEREFERENCE(Argument);
  double x = DOUBLEVALUE(Argument);
  Argument = besARGUMENT(2);
  besDEREFERENCE(Argument);
  double y = DOUBLEVALUE(Argument);
  Argument = besARGUMENT(3);
  besDEREFERENCE(Argument);
  double z = DOUBLEVALUE(Argument);

  besRETURN_DOUBLE(gsl_hypot3(x, y, z));
besEND

I'm wondering if this could be re-coded as:
Code: [Select]
besFUNCTION(_hypot3)
  double x,y,z;
  
  besARGUMENTS("rrr")
    &x,&y,&z
  besARGEND  

  besRETURN_DOUBLE(gsl_hypot3(x, y, z));
besEND

"rrr" above specifies that the 3 arguments should be Double values (not sure why it isn't "d" for clarity, but that's how it's set up internally. I guess "r" stands for "real" which I suppose is analogous to a Double?).

A.
Title: Re: ScriptBasic O2h Embedding
Post by: JRS on May 28, 2011, 06:25:11 PM
Here is the source for the GSL extension module supporting the Elementary Functions.

Code: [Select]
/*
   GNU Scientific Library
   Based on GSL 1.15
   Interface By: John Spikowski
   Refinements By: Armando I. Rivera (AIR)
   Version 0.01
*/

#include <stdio.h>
#include "../../basext.h"
#include <gsl/gsl_math.h>
      
besVERSION_NEGOTIATE
    return (int)INTERFACE_VERSION;
besEND

besSUB_START

besEND

besSUB_FINISH

besEND

/* Elementary Functions */

besFUNCTION(_log1p)
  double x;

  besARGUMENTS("r")
    &x
  besARGEND  

  besRETURN_DOUBLE(gsl_log1p(x));
besEND


besFUNCTION(_expm1)
  double x;

  besARGUMENTS("r")
    &x
  besARGEND  

  besRETURN_DOUBLE(gsl_expm1(x));
besEND


besFUNCTION(_hypot)
  double x,y;

  besARGUMENTS("rr")
    &x,&y
  besARGEND  

  besRETURN_DOUBLE(gsl_hypot(x, y));
besEND


besFUNCTION(_hypot3)
  double x,y,z;
  
  besARGUMENTS("rrr")
    &x,&y,&z
  besARGEND  

  besRETURN_DOUBLE(gsl_hypot3(x, y, z));
besEND


besFUNCTION(_acosh)
  double x;

  besARGUMENTS("r")
    &x
  besARGEND  

  besRETURN_DOUBLE(gsl_acosh(x));
besEND


besFUNCTION(_asinh)
  double x;

  besARGUMENTS("r")
    &x
  besARGEND  

  besRETURN_DOUBLE(gsl_asinh(x));
besEND


besFUNCTION(_atanh)
  double x;

  besARGUMENTS("r")
    &x
  besARGEND  

  besRETURN_DOUBLE(gsl_atanh(x));
besEND


besFUNCTION(_ldexp)
  double x;
  int y;

  besARGUMENTS("ri")
    &x,&y
  besARGEND  

  besRETURN_DOUBLE(gsl_ldexp(x, y));
besEND


besFUNCTION(_frexp)
  double f;
  LEFTVALUE e;

  besARGUMENTS("r")
    &f
  besARGEND
  besLEFTVALUE(besARGUMENT(2),e);
  
  besRETURN_DOUBLE(gsl_frexp(f, *e));
besEND

Calling GSL SB extension module functions:

log1p()

Code: [Select]
DECLARE SUB log1p ALIAS "_log1p" LIB "gsl"

PRINT FORMAT("%.32g", log1p(34.0)),"\n"

3.5553480614894135136694330867613

frexp()

Code: [Select]
DECLARE SUB frexp ALIAS "_frexp" LIB "gsl"

x = 16.4
e = 0
fraction = frexp(x, e)

PRINT FORMAT("%g",fraction),"\n"
PRINT e,"\n"

0.5125
5